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.cc588
1 files changed, 338 insertions, 250 deletions
diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc
index 09920241ee..7e3e6556a1 100644
--- a/deps/v8/src/ic/ic.cc
+++ b/deps/v8/src/ic/ic.cc
@@ -9,13 +9,11 @@
#include "src/api.h"
#include "src/arguments.h"
#include "src/base/bits.h"
-#include "src/codegen.h"
#include "src/conversions.h"
#include "src/execution.h"
#include "src/field-type.h"
#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-inl.h"
#include "src/ic/ic-stats.h"
@@ -52,8 +50,14 @@ char IC::TransitionMarkFromState(IC::State state) {
UNREACHABLE();
}
+namespace {
-const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
+const char* GetModifier(KeyedAccessLoadMode mode) {
+ if (mode == LOAD_IGNORE_OUT_OF_BOUNDS) return ".IGNORE_OOB";
+ return "";
+}
+
+const char* GetModifier(KeyedAccessStoreMode mode) {
if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
return ".IGNORE_OOB";
@@ -62,6 +66,8 @@ const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
return "";
}
+} // namespace
+
#define TRACE_GENERIC_IC(reason) set_slow_stub_reason(reason);
void IC::TraceIC(const char* type, Handle<Object> name) {
@@ -72,36 +78,6 @@ void IC::TraceIC(const char* type, Handle<Object> name) {
}
}
-Address IC::GetAbstractPC(int* line, int* column) const {
- JavaScriptFrameIterator it(isolate());
-
- JavaScriptFrame* frame = it.frame();
- DCHECK(!frame->is_builtin());
- int position = frame->position();
-
- Object* maybe_script = frame->function()->shared()->script();
- if (maybe_script->IsScript()) {
- Handle<Script> script(Script::cast(maybe_script), isolate());
- Script::PositionInfo info;
- Script::GetPositionInfo(script, position, &info, Script::WITH_OFFSET);
- *line = info.line + 1;
- *column = info.column + 1;
- } else {
- *line = position;
- *column = -1;
- }
-
- if (frame->is_interpreted()) {
- InterpretedFrame* iframe = static_cast<InterpretedFrame*>(frame);
- Address bytecode_start =
- reinterpret_cast<Address>(iframe->GetBytecodeArray()) - kHeapObjectTag +
- BytecodeArray::kHeaderSize;
- return bytecode_start + iframe->GetBytecodeOffset();
- }
-
- return frame->pc();
-}
-
void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
State new_state) {
if (V8_LIKELY(!FLAG_ic_stats)) return;
@@ -112,18 +88,19 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
}
const char* modifier = "";
- if (IsKeyedStoreIC()) {
+ if (IsKeyedLoadIC()) {
+ KeyedAccessLoadMode mode =
+ casted_nexus<KeyedLoadICNexus>()->GetKeyedAccessLoadMode();
+ modifier = GetModifier(mode);
+ } else if (IsKeyedStoreIC()) {
KeyedAccessStoreMode mode =
casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
- modifier = GetTransitionMarkModifier(mode);
+ modifier = GetModifier(mode);
}
if (!(FLAG_ic_stats &
v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING)) {
- int line;
- int column;
- Address pc = GetAbstractPC(&line, &column);
- LOG(isolate(), ICEvent(type, is_keyed(), pc, line, column, map, *name,
+ LOG(isolate(), ICEvent(type, is_keyed(), map, *name,
TransitionMarkFromState(old_state),
TransitionMarkFromState(new_state), modifier,
slow_stub_reason_));
@@ -181,7 +158,7 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
// levels of the stack frame iteration code. This yields a ~35% speedup when
// running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
- Address* constant_pool = NULL;
+ Address* constant_pool = nullptr;
if (FLAG_enable_embedded_constant_pool) {
constant_pool = reinterpret_cast<Address*>(
entry + ExitFrameConstants::kConstantPoolOffset);
@@ -288,7 +265,7 @@ bool IC::ShouldRecomputeHandler(Handle<String> name) {
if (maybe_handler_.is_null()) {
if (!receiver_map()->IsJSObjectMap()) return false;
Map* first_map = FirstTargetMap();
- if (first_map == NULL) return false;
+ if (first_map == nullptr) return false;
Handle<Map> old_map(first_map);
if (old_map->is_deprecated()) return true;
return IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
@@ -341,18 +318,43 @@ MaybeHandle<Object> IC::ReferenceError(Handle<Name> name) {
// static
void IC::OnFeedbackChanged(Isolate* isolate, FeedbackVector* vector,
- JSFunction* host_function) {
+ FeedbackSlot slot, JSFunction* host_function,
+ const char* reason) {
if (FLAG_trace_opt_verbose) {
// TODO(leszeks): The host function is only needed for this print, we could
// remove it as a parameter if we're of with removing this trace (or only
// tracing the feedback vector, not the function name).
if (vector->profiler_ticks() != 0) {
PrintF("[resetting ticks for ");
- host_function->PrintName();
- PrintF(" due from %d due to IC change]\n", vector->profiler_ticks());
+ host_function->ShortPrint();
+ PrintF(" due from %d due to IC change: %s]\n", vector->profiler_ticks(),
+ reason);
}
}
vector->set_profiler_ticks(0);
+
+#ifdef V8_TRACE_FEEDBACK_UPDATES
+ if (FLAG_trace_feedback_updates) {
+ int slot_count = vector->metadata()->slot_count();
+
+ OFStream os(stdout);
+ if (slot.IsInvalid()) {
+ os << "[Feedback slots in ";
+ } else {
+ os << "[Feedback slot " << slot.ToInt() << "/" << slot_count << " in ";
+ }
+ vector->shared_function_info()->ShortPrint(os);
+ if (slot.IsInvalid()) {
+ os << " updated - ";
+ } else {
+ os << " updated to ";
+ vector->FeedbackSlotPrint(os, slot);
+ os << " - ";
+ }
+ os << reason << "]" << std::endl;
+ }
+#endif
+
isolate->runtime_profiler()->NotifyICChanged();
// TODO(2029): When an optimized function is patched, it would
// be nice to propagate the corresponding type information to its
@@ -367,18 +369,25 @@ static bool MigrateDeprecated(Handle<Object> object) {
return true;
}
-void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
+bool IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
+ bool changed = true;
if (new_state == PREMONOMORPHIC) {
nexus()->ConfigurePremonomorphic();
} else if (new_state == MEGAMORPHIC) {
DCHECK_IMPLIES(!is_keyed(), key->IsName());
- nexus()->ConfigureMegamorphic(key->IsName() ? PROPERTY : ELEMENT);
+ // Even though we don't change the feedback data, we still want to reset the
+ // profiler ticks. Real-world observations suggest that optimizing these
+ // functions doesn't improve performance.
+ changed = nexus()->ConfigureMegamorphic(key->IsName() ? PROPERTY : ELEMENT);
} else {
UNREACHABLE();
}
vector_set_ = true;
- OnFeedbackChanged(isolate(), *vector(), GetHostFunction());
+ OnFeedbackChanged(
+ isolate(), *vector(), slot(), GetHostFunction(),
+ new_state == PREMONOMORPHIC ? "Premonomorphic" : "Megamorphic");
+ return changed;
}
void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
@@ -393,7 +402,8 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
}
vector_set_ = true;
- OnFeedbackChanged(isolate(), *vector(), GetHostFunction());
+ OnFeedbackChanged(isolate(), *vector(), slot(), GetHostFunction(),
+ IsLoadGlobalIC() ? "LoadGlobal" : "Monomorphic");
}
void IC::ConfigureVectorState(Handle<Name> name, MapHandles const& maps,
@@ -404,14 +414,15 @@ void IC::ConfigureVectorState(Handle<Name> name, MapHandles const& maps,
nexus()->ConfigurePolymorphic(name, maps, handlers);
vector_set_ = true;
- OnFeedbackChanged(isolate(), *vector(), GetHostFunction());
+ OnFeedbackChanged(isolate(), *vector(), slot(), GetHostFunction(),
+ "Polymorphic");
}
MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
// If the object is undefined or null it's illegal to try to get any
// of its properties; throw a TypeError in that case.
if (object->IsNullOrUndefined(isolate())) {
- if (FLAG_use_ic && state() != UNINITIALIZED && state() != PREMONOMORPHIC) {
+ if (FLAG_use_ic && state() != PREMONOMORPHIC) {
// Ensure the IC state progresses.
TRACE_HANDLER_STATS(isolate(), LoadIC_NonReceiver);
update_receiver_map(object);
@@ -635,11 +646,6 @@ void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
}
}
-Handle<Smi> LoadIC::SimpleFieldLoad(Isolate* isolate, FieldIndex index) {
- TRACE_HANDLER_STATS(isolate, LoadIC_LoadFieldDH);
- return LoadHandler::LoadField(isolate, index);
-}
-
void LoadIC::UpdateCaches(LookupIterator* lookup) {
if (state() == UNINITIALIZED && !IsLoadGlobalIC()) {
// This is the first time we execute this inline cache. Set the target to
@@ -705,38 +711,25 @@ void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) {
}
}
-Handle<Object> IC::ComputeHandler(LookupIterator* lookup) {
- // Try to find a globally shared handler stub.
- Handle<Object> shared_handler = GetMapIndependentHandler(lookup);
- if (!shared_handler.is_null()) {
- DCHECK(IC::IsHandler(*shared_handler));
- return shared_handler;
- }
-
- return CompileHandler(lookup);
-}
-
-Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
+Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
Handle<Object> receiver = lookup->GetReceiver();
if (receiver->IsString() &&
*lookup->name() == isolate()->heap()->length_string()) {
- FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
- return SimpleFieldLoad(isolate(), index);
+ TRACE_HANDLER_STATS(isolate(), LoadIC_StringLength);
+ return BUILTIN_CODE(isolate(), LoadIC_StringLength);
}
if (receiver->IsStringWrapper() &&
*lookup->name() == isolate()->heap()->length_string()) {
- TRACE_HANDLER_STATS(isolate(), LoadIC_StringLength);
- return BUILTIN_CODE(isolate(), LoadIC_StringLength);
+ TRACE_HANDLER_STATS(isolate(), LoadIC_StringWrapperLength);
+ return BUILTIN_CODE(isolate(), LoadIC_StringWrapperLength);
}
// Use specialized code for getting prototype of functions.
if (receiver->IsJSFunction() &&
*lookup->name() == isolate()->heap()->prototype_string() &&
- receiver->IsConstructor() &&
- !Handle<JSFunction>::cast(receiver)
- ->map()
- ->has_non_instance_prototype()) {
+ JSFunction::cast(*receiver)->has_prototype_slot() &&
+ !JSFunction::cast(*receiver)->map()->has_non_instance_prototype()) {
Handle<Code> stub;
TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub);
return BUILTIN_CODE(isolate(), LoadIC_FunctionPrototype);
@@ -779,11 +772,10 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
// Use simple field loads for some well-known callback properties.
// The method will only return true for absolute truths based on the
// receiver maps.
- int object_offset;
- if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
- &object_offset)) {
- FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map);
- return SimpleFieldLoad(isolate(), index);
+ FieldIndex index;
+ if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(), &index)) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH);
+ return LoadHandler::LoadField(isolate(), index);
}
if (holder->IsJSModuleNamespace()) {
Handle<ObjectHashTable> exports(
@@ -792,7 +784,7 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
int entry = exports->FindEntry(isolate(), lookup->name(),
Smi::ToInt(lookup->name()->GetHash()));
// We found the accessor, so the entry must exist.
- DCHECK(entry != ObjectHashTable::kNotFound);
+ DCHECK_NE(entry, ObjectHashTable::kNotFound);
int index = ObjectHashTable::EntryToValueIndex(entry);
return LoadHandler::LoadModuleExport(isolate(), index);
}
@@ -817,6 +809,8 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
return slow_stub();
}
+ Handle<Smi> smi_handler;
+
CallOptimization call_optimization(getter);
if (call_optimization.is_simple_api_call()) {
if (!call_optimization.IsCompatibleReceiverMap(map, holder) ||
@@ -824,38 +818,46 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
return slow_stub();
}
- break;
- }
- // FunctionTemplate isn't yet supported as smi-handler.
- if (getter->IsFunctionTemplateInfo()) {
- if (!holder->HasFastProperties()) {
- TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
- return slow_stub();
- }
- break;
+ CallOptimization::HolderLookup holder_lookup;
+ call_optimization.LookupHolderOfExpectedType(map, &holder_lookup);
+
+ smi_handler = LoadHandler::LoadApiGetter(
+ isolate(), holder_lookup == CallOptimization::kHolderIsReceiver);
+
+ Handle<Context> context(
+ call_optimization.GetAccessorContext(holder->map()));
+ Handle<WeakCell> context_cell =
+ isolate()->factory()->NewWeakCell(context);
+ Handle<WeakCell> data_cell = isolate()->factory()->NewWeakCell(
+ call_optimization.api_call_info());
+ Handle<Tuple2> data =
+ isolate()->factory()->NewTuple2(context_cell, data_cell, TENURED);
+
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterFromPrototypeDH);
+ return LoadHandler::LoadFromPrototype(
+ isolate(), map, holder, lookup->name(), smi_handler, data);
}
- Handle<Smi> smi_handler;
if (holder->HasFastProperties()) {
smi_handler =
LoadHandler::LoadAccessor(isolate(), lookup->GetAccessorIndex());
- if (receiver_is_holder) {
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadAccessorDH);
- return smi_handler;
- }
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadAccessorDH);
+ if (receiver_is_holder) return smi_handler;
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadAccessorFromPrototypeDH);
} else if (holder->IsJSGlobalObject()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalFromPrototypeDH);
smi_handler = LoadHandler::LoadGlobal(isolate());
+ Handle<WeakCell> cell =
+ isolate()->factory()->NewWeakCell(lookup->GetPropertyCell());
+ return LoadHandler::LoadFromPrototype(
+ isolate(), map, holder, lookup->name(), smi_handler, cell);
} else {
smi_handler = LoadHandler::LoadNormal(isolate());
- if (receiver_is_holder) {
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
- return smi_handler;
- }
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
+ if (receiver_is_holder) return smi_handler;
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
}
@@ -873,11 +875,12 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
return slow_stub();
}
- Handle<Smi> smi_handler =
- LoadHandler::LoadApiGetter(isolate(), lookup->GetAccessorIndex());
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterDH);
+ Handle<Smi> smi_handler = LoadHandler::LoadNativeDataProperty(
+ isolate(), lookup->GetAccessorIndex());
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNativeDataPropertyDH);
if (receiver_is_holder) return smi_handler;
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterFromPrototypeDH);
+ TRACE_HANDLER_STATS(isolate(),
+ LoadIC_LoadNativeDataPropertyFromPrototypeDH);
return LoadHandler::LoadFromPrototype(isolate(), map, holder,
lookup->name(), smi_handler);
}
@@ -886,31 +889,26 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
DCHECK_EQ(kData, lookup->property_details().kind());
Handle<Smi> smi_handler;
if (lookup->is_dictionary_holder()) {
- smi_handler = LoadHandler::LoadNormal(isolate());
- if (receiver_is_holder) {
- if (holder->IsJSGlobalObject()) {
- // TODO(verwaest): This is a workaround for code that leaks the
- // global object.
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalDH);
- smi_handler = LoadHandler::LoadGlobal(isolate());
- return LoadHandler::LoadFromPrototype(isolate(), map, holder,
- lookup->name(), smi_handler);
- }
- DCHECK(!holder->IsJSGlobalObject());
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
- return smi_handler;
- }
-
if (holder->IsJSGlobalObject()) {
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalFromPrototypeDH);
+ // TODO(verwaest): Also supporting the global object as receiver is a
+ // workaround for code that leaks the global object.
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalDH);
smi_handler = LoadHandler::LoadGlobal(isolate());
- } else {
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
+ Handle<WeakCell> cell =
+ isolate()->factory()->NewWeakCell(lookup->GetPropertyCell());
+ return LoadHandler::LoadFromPrototype(
+ isolate(), map, holder, lookup->name(), smi_handler, cell);
}
+ smi_handler = LoadHandler::LoadNormal(isolate());
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
+ if (receiver_is_holder) return smi_handler;
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
+
} else if (lookup->property_details().location() == kField) {
FieldIndex field = lookup->GetFieldIndex();
- smi_handler = SimpleFieldLoad(isolate(), field);
+ smi_handler = LoadHandler::LoadField(isolate(), field);
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH);
if (receiver_is_holder) return smi_handler;
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
} else {
@@ -946,28 +944,6 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
return Handle<Code>::null();
}
-Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup) {
- DCHECK_EQ(LookupIterator::ACCESSOR, lookup->state());
- Handle<JSObject> holder = lookup->GetHolder<JSObject>();
- Handle<Map> map = receiver_map();
-
- Handle<Object> accessors = lookup->GetAccessors();
- DCHECK(accessors->IsAccessorPair());
- DCHECK(holder->HasFastProperties());
- DCHECK(!GetHostFunction()->shared()->HasBreakInfo());
- Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
- isolate());
- CallOptimization call_optimization(getter);
- NamedLoadHandlerCompiler compiler(isolate(), map, holder);
- DCHECK(call_optimization.is_simple_api_call());
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
- int index = lookup->GetAccessorIndex();
- Handle<Code> code = compiler.CompileLoadCallback(
- lookup->name(), call_optimization, index, slow_stub());
- return code;
-}
-
-
static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
// This helper implements a few common fast cases for converting
// non-smi keys of keyed loads/stores to a smi or a string.
@@ -989,14 +965,21 @@ static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
return key;
}
-void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
+bool KeyedLoadIC::CanChangeToAllowOutOfBounds(Handle<Map> receiver_map) {
+ Handle<Object> handler;
+ return nexus()->FindHandlerForMap(receiver_map).ToHandle(&handler) &&
+ LoadHandler::GetKeyedAccessLoadMode(*handler) == STANDARD_LOAD;
+}
+
+void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver,
+ KeyedAccessLoadMode load_mode) {
Handle<Map> receiver_map(receiver->map(), isolate());
DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE); // Checked by caller.
MapHandles target_receiver_maps;
TargetMaps(&target_receiver_maps);
if (target_receiver_maps.empty()) {
- Handle<Object> handler = LoadElementHandler(receiver_map);
+ Handle<Object> handler = LoadElementHandler(receiver_map, load_mode);
return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
}
@@ -1024,7 +1007,7 @@ void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
IsMoreGeneralElementsKindTransition(
target_receiver_maps.at(0)->elements_kind(),
Handle<JSObject>::cast(receiver)->GetElementsKind())) {
- Handle<Object> handler = LoadElementHandler(receiver_map);
+ Handle<Object> handler = LoadElementHandler(receiver_map, load_mode);
return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
}
@@ -1033,10 +1016,16 @@ void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
// Determine the list of receiver maps that this call site has seen,
// adding the map that was just encountered.
if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
- // If the miss wasn't due to an unseen map, a polymorphic stub
- // won't help, use the generic stub.
- TRACE_GENERIC_IC("same map added twice");
- return;
+ // If the {receiver_map} previously had a handler that didn't handle
+ // out-of-bounds access, but can generally handle it, we can just go
+ // on and update the handler appropriately below.
+ if (load_mode != LOAD_IGNORE_OUT_OF_BOUNDS ||
+ !CanChangeToAllowOutOfBounds(receiver_map)) {
+ // If the miss wasn't due to an unseen map, a polymorphic stub
+ // won't help, use the generic stub.
+ TRACE_GENERIC_IC("same map added twice");
+ return;
+ }
}
// If the maximum number of receiver maps has been exceeded, use the generic
@@ -1048,7 +1037,7 @@ void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
ObjectHandles handlers;
handlers.reserve(target_receiver_maps.size());
- LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers);
+ LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers, load_mode);
DCHECK_LE(1, target_receiver_maps.size());
if (target_receiver_maps.size() == 1) {
ConfigureVectorState(Handle<Name>(), target_receiver_maps[0], handlers[0]);
@@ -1057,7 +1046,8 @@ void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
}
}
-Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) {
+Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map,
+ KeyedAccessLoadMode load_mode) {
if (receiver_map->has_indexed_interceptor() &&
!receiver_map->GetIndexedInterceptor()->getter()->IsUndefined(
isolate()) &&
@@ -1065,11 +1055,11 @@ Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) {
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub);
return LoadIndexedInterceptorStub(isolate()).GetCode();
}
- if (receiver_map->IsStringMap()) {
- TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedStringStub);
- return BUILTIN_CODE(isolate(), KeyedLoadIC_IndexedString);
- }
InstanceType instance_type = receiver_map->instance_type();
+ if (instance_type < FIRST_NONSTRING_TYPE) {
+ TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedStringDH);
+ return LoadHandler::LoadIndexedString(isolate(), load_mode);
+ }
if (instance_type < FIRST_JS_RECEIVER_TYPE) {
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_SlowStub);
return BUILTIN_CODE(isolate(), KeyedLoadIC_Slow);
@@ -1087,7 +1077,7 @@ Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) {
if (elements_kind == DICTIONARY_ELEMENTS) {
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
return LoadHandler::LoadElement(isolate(), elements_kind, false,
- is_js_array);
+ is_js_array, load_mode);
}
DCHECK(IsFastElementsKind(elements_kind) ||
IsFixedTypedArrayElementsKind(elements_kind));
@@ -1098,11 +1088,13 @@ Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) {
isolate()->raw_native_context()->GetInitialJSArrayMap(elements_kind);
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
return LoadHandler::LoadElement(isolate(), elements_kind,
- convert_hole_to_undefined, is_js_array);
+ convert_hole_to_undefined, is_js_array,
+ load_mode);
}
-void KeyedLoadIC::LoadElementPolymorphicHandlers(MapHandles* receiver_maps,
- ObjectHandles* handlers) {
+void KeyedLoadIC::LoadElementPolymorphicHandlers(
+ MapHandles* receiver_maps, ObjectHandles* handlers,
+ KeyedAccessLoadMode load_mode) {
// Filter out deprecated maps to ensure their instances get migrated.
receiver_maps->erase(
std::remove_if(
@@ -1120,10 +1112,61 @@ void KeyedLoadIC::LoadElementPolymorphicHandlers(MapHandles* receiver_maps,
receiver_map->NotifyLeafMapLayoutChange();
}
}
- handlers->push_back(LoadElementHandler(receiver_map));
+ handlers->push_back(LoadElementHandler(receiver_map, load_mode));
+ }
+}
+
+namespace {
+
+bool IsOutOfBoundsAccess(Handle<Object> receiver, uint32_t index) {
+ uint32_t length = 0;
+ if (receiver->IsJSArray()) {
+ JSArray::cast(*receiver)->length()->ToArrayLength(&length);
+ } else if (receiver->IsString()) {
+ length = String::cast(*receiver)->length();
+ } else if (receiver->IsJSObject()) {
+ length = JSObject::cast(*receiver)->elements()->length();
+ } else {
+ return false;
+ }
+ return index >= length;
+}
+
+KeyedAccessLoadMode GetLoadMode(Handle<Object> receiver, uint32_t index) {
+ if (IsOutOfBoundsAccess(receiver, index)) {
+ if (receiver->IsJSTypedArray()) {
+ // For JSTypedArray we never lookup elements in the prototype chain.
+ return LOAD_IGNORE_OUT_OF_BOUNDS;
+ }
+
+ // For other {receiver}s we need to check the "no elements" protector.
+ Isolate* isolate = Handle<HeapObject>::cast(receiver)->GetIsolate();
+ if (isolate->IsNoElementsProtectorIntact()) {
+ if (receiver->IsString()) {
+ // ToObject(receiver) will have the initial String.prototype.
+ return LOAD_IGNORE_OUT_OF_BOUNDS;
+ }
+ if (receiver->IsJSObject()) {
+ // For other JSObjects (including JSArrays) we can only continue if
+ // the {receiver}s prototype is either the initial Object.prototype
+ // or the initial Array.prototype, which are both guarded by the
+ // "no elements" protector checked above.
+ Handle<Object> receiver_prototype(
+ JSObject::cast(*receiver)->map()->prototype(), isolate);
+ if (isolate->IsInAnyContext(*receiver_prototype,
+ Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ||
+ isolate->IsInAnyContext(*receiver_prototype,
+ Context::INITIAL_OBJECT_PROTOTYPE_INDEX)) {
+ return LOAD_IGNORE_OUT_OF_BOUNDS;
+ }
+ }
+ }
}
+ return STANDARD_LOAD;
}
+} // namespace
+
MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
Handle<Object> key) {
if (MigrateDeprecated(object)) {
@@ -1149,9 +1192,10 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
Object);
} else if (FLAG_use_ic && !object->IsAccessCheckNeeded() &&
!object->IsJSValue()) {
- if ((object->IsJSReceiver() && key->IsSmi()) ||
- (object->IsString() && key->IsNumber())) {
- UpdateLoadElement(Handle<HeapObject>::cast(object));
+ if ((object->IsJSReceiver() || object->IsString()) &&
+ key->ToArrayIndex(&index)) {
+ KeyedAccessLoadMode load_mode = GetLoadMode(object, index);
+ UpdateLoadElement(Handle<HeapObject>::cast(object), load_mode);
if (is_vector_set()) {
TRACE_IC("LoadIC", key);
}
@@ -1301,7 +1345,7 @@ 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 (FLAG_use_ic && state() != UNINITIALIZED && state() != PREMONOMORPHIC) {
+ if (FLAG_use_ic && state() != PREMONOMORPHIC) {
// Ensure the IC state progresses.
TRACE_HANDLER_STATS(isolate(), StoreIC_NonReceiver);
update_receiver_map(object);
@@ -1353,6 +1397,7 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
if (created_new_transition_) {
// The first time a transition is performed, there's a good chance that
// it won't be taken again, so don't bother creating a handler.
+ TRACE_GENERIC_IC("new transition");
TRACE_IC("StoreIC", lookup->name());
return;
}
@@ -1366,7 +1411,7 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
TRACE_IC("StoreIC", lookup->name());
}
-Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
+Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
switch (lookup->state()) {
case LookupIterator::TRANSITION: {
Handle<JSObject> holder = lookup->GetHolder<JSObject>();
@@ -1375,9 +1420,20 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
if (store_target->IsJSGlobalObject()) {
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransitionDH);
- Handle<Object> handler = StoreHandler::StoreTransition(
- isolate(), receiver_map(), store_target, lookup->transition_cell(),
- lookup->name());
+ if (receiver_map()->IsJSGlobalObject()) {
+ DCHECK(IsStoreGlobalIC());
+ DCHECK_EQ(*lookup->GetReceiver(), *holder);
+ DCHECK_EQ(*store_target, *holder);
+ return StoreHandler::StoreGlobal(isolate(),
+ lookup->transition_cell());
+ }
+
+ Handle<Smi> smi_handler = StoreHandler::StoreGlobalProxy(isolate());
+ Handle<WeakCell> cell =
+ isolate()->factory()->NewWeakCell(lookup->transition_cell());
+ Handle<Object> handler = StoreHandler::StoreThroughPrototype(
+ isolate(), receiver_map(), store_target, lookup->name(),
+ smi_handler, cell);
return handler;
}
// Currently not handled by CompileStoreTransition.
@@ -1389,9 +1445,19 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
DCHECK(lookup->IsCacheableTransition());
Handle<Map> transition = lookup->transition_map();
- TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransitionDH);
- Handle<Object> handler = StoreHandler::StoreTransition(
- isolate(), receiver_map(), holder, transition, lookup->name());
+
+ Handle<Smi> smi_handler;
+ if (transition->is_dictionary_map()) {
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH);
+ smi_handler = StoreHandler::StoreNormal(isolate());
+ } else {
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransitionDH);
+ smi_handler = StoreHandler::StoreTransition(isolate(), transition);
+ }
+
+ Handle<WeakCell> cell = Map::WeakCellForMap(transition);
+ Handle<Object> handler = StoreHandler::StoreThroughPrototype(
+ isolate(), receiver_map(), holder, lookup->name(), smi_handler, cell);
TransitionsAccessor(receiver_map())
.UpdateHandler(*lookup->name(), *handler);
return handler;
@@ -1438,7 +1504,16 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
}
- break; // Custom-compiled handler.
+
+ Handle<Smi> smi_handler = StoreHandler::StoreNativeDataProperty(
+ isolate(), lookup->GetAccessorIndex());
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNativeDataPropertyDH);
+ if (receiver.is_identical_to(holder)) return smi_handler;
+ TRACE_HANDLER_STATS(isolate(),
+ StoreIC_StoreNativeDataPropertyOnPrototypeDH);
+ return StoreHandler::StoreThroughPrototype(
+ isolate(), receiver_map(), holder, lookup->name(), smi_handler);
+
} else if (accessors->IsAccessorPair()) {
Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
isolate());
@@ -1450,13 +1525,45 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
CallOptimization call_optimization(setter);
if (call_optimization.is_simple_api_call()) {
if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
- break; // Custom-compiled handler.
+ CallOptimization::HolderLookup holder_lookup;
+ call_optimization.LookupHolderOfExpectedType(receiver_map(),
+ &holder_lookup);
+
+ Handle<Smi> smi_handler = StoreHandler::StoreApiSetter(
+ isolate(),
+ holder_lookup == CallOptimization::kHolderIsReceiver);
+
+ Handle<Context> context(
+ call_optimization.GetAccessorContext(holder->map()));
+ Handle<WeakCell> context_cell =
+ isolate()->factory()->NewWeakCell(context);
+ Handle<WeakCell> data_cell = isolate()->factory()->NewWeakCell(
+ call_optimization.api_call_info());
+ Handle<Tuple2> data = isolate()->factory()->NewTuple2(
+ context_cell, data_cell, TENURED);
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreApiSetterOnPrototypeDH);
+ return StoreHandler::StoreThroughPrototype(
+ isolate(), receiver_map(), holder, lookup->name(), smi_handler,
+ data);
}
TRACE_GENERIC_IC("incompatible receiver");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
+ } else if (setter->IsFunctionTemplateInfo()) {
+ TRACE_GENERIC_IC("setter non-simple template");
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return slow_stub();
}
- break; // Custom-compiled handler.
+
+ Handle<Smi> smi_handler =
+ StoreHandler::StoreAccessor(isolate(), lookup->GetAccessorIndex());
+
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreAccessorDH);
+ if (receiver.is_identical_to(holder)) return smi_handler;
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreAccessorOnPrototypeDH);
+
+ return StoreHandler::StoreThroughPrototype(
+ isolate(), receiver_map(), holder, lookup->name(), smi_handler);
}
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
@@ -1518,57 +1625,6 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
return Handle<Code>::null();
}
-Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup) {
- DCHECK_EQ(LookupIterator::ACCESSOR, 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());
-
- 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()));
- TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
- NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
- // TODO(ishell): don't hard-code language mode into the handler because
- // this handler can be re-used through megamorphic stub cache for wrong
- // language mode.
- // Better pass vector/slot to Runtime::kStoreCallbackProperty and
- // let it decode the language mode from the IC kind.
- Handle<Code> code = compiler.CompileStoreCallback(receiver, lookup->name(),
- info, language_mode());
- return code;
- }
-
- 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);
- Handle<Code> code = compiler.CompileStoreCallback(
- receiver, lookup->name(), call_optimization, lookup->GetAccessorIndex(),
- slow_stub());
- return code;
- }
- 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);
-}
-
void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
KeyedAccessStoreMode store_mode) {
MapHandles target_receiver_maps;
@@ -1744,6 +1800,7 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
stub =
StoreFastElementStub(isolate(), is_jsarray, elements_kind, store_mode)
.GetCode();
+ if (receiver_map->has_fixed_typed_array_elements()) return stub;
} else {
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind);
@@ -1812,16 +1869,6 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
}
}
-bool IsOutOfBoundsAccess(Handle<JSObject> receiver, uint32_t index) {
- uint32_t length = 0;
- if (receiver->IsJSArray()) {
- JSArray::cast(*receiver)->length()->ToArrayLength(&length);
- } else {
- length = static_cast<uint32_t>(receiver->elements()->length());
- }
- return index >= length;
-}
-
static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
uint32_t index, Handle<Object> value) {
@@ -1902,16 +1949,15 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
JSReceiver::MAY_BE_STORE_FROM_KEYED),
Object);
if (vector_needs_update()) {
- ConfigureVectorState(MEGAMORPHIC, key);
- TRACE_GENERIC_IC("unhandled internalized string key");
- TRACE_IC("StoreIC", key);
+ if (ConfigureVectorState(MEGAMORPHIC, key)) {
+ TRACE_GENERIC_IC("unhandled internalized string key");
+ TRACE_IC("StoreIC", key);
+ }
}
return store_handle;
}
- if (state() != UNINITIALIZED) {
- JSObject::MakePrototypesFast(object, kStartAtPrototype, isolate());
- }
+ JSObject::MakePrototypesFast(object, kStartAtPrototype, isolate());
bool use_ic = FLAG_use_ic && !object->IsStringWrapper() &&
!object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy();
@@ -2139,6 +2185,48 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
}
}
+RUNTIME_FUNCTION(Runtime_StoreGlobalIC_Slow) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(5, args.length());
+ // Runtime functions don't follow the IC's calling convention.
+ Handle<Object> value = args.at(0);
+ Handle<Smi> slot = args.at<Smi>(1);
+ Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
+ Handle<Object> object = args.at(3);
+ CONVERT_ARG_HANDLE_CHECKED(String, name, 4);
+
+ Handle<Context> native_context = isolate->native_context();
+ Handle<ScriptContextTable> script_contexts(
+ native_context->script_context_table());
+
+ ScriptContextTable::LookupResult lookup_result;
+ if (ScriptContextTable::Lookup(script_contexts, name, &lookup_result)) {
+ Handle<Context> script_context = ScriptContextTable::GetContext(
+ script_contexts, lookup_result.context_index);
+ if (lookup_result.mode == CONST) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError(MessageTemplate::kConstAssign, object, name));
+ }
+
+ Handle<Object> previous_value =
+ FixedArray::get(*script_context, lookup_result.slot_index, isolate);
+
+ if (previous_value->IsTheHole(isolate)) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
+ }
+
+ script_context->set(lookup_result.slot_index, *value);
+ return *value;
+ }
+
+ FeedbackSlot vector_slot = vector->ToSlot(slot->value());
+ LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
+ RETURN_RESULT_OR_FAILURE(
+ isolate,
+ Runtime::SetObjectProperty(isolate, object, name, value, language_mode));
+}
+
// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
HandleScope scope(isolate);
@@ -2228,10 +2316,10 @@ RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
Address setter_address = v8::ToCData<Address>(callback->setter());
v8::AccessorNameSetterCallback fun =
FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address);
- DCHECK(fun != NULL);
+ DCHECK_NOT_NULL(fun);
- Object::ShouldThrow should_throw =
- is_sloppy(language_mode) ? Object::DONT_THROW : Object::THROW_ON_ERROR;
+ ShouldThrow should_throw =
+ is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver,
*holder, should_throw);
custom_args.Call(fun, name, value);
@@ -2258,7 +2346,7 @@ RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {
InterceptorInfo* interceptor = holder->GetNamedInterceptor();
PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
- *holder, Object::DONT_THROW);
+ *holder, kDontThrow);
v8::GenericNamedPropertyGetterCallback getter =
v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
@@ -2314,7 +2402,7 @@ RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) {
InterceptorInfo* interceptor = receiver->GetNamedInterceptor();
DCHECK(!interceptor->non_masking());
PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
- *receiver, Object::DONT_THROW);
+ *receiver, kDontThrow);
v8::GenericNamedPropertySetterCallback setter =
v8::ToCData<v8::GenericNamedPropertySetterCallback>(
@@ -2344,12 +2432,12 @@ RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) {
// TODO(verwaest): This should probably get the holder and receiver as input.
HandleScope scope(isolate);
Handle<JSObject> receiver = args.at<JSObject>(0);
- DCHECK(args.smi_at(1) >= 0);
+ DCHECK_GE(args.smi_at(1), 0);
uint32_t index = args.smi_at(1);
InterceptorInfo* interceptor = receiver->GetIndexedInterceptor();
PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
- *receiver, Object::DONT_THROW);
+ *receiver, kDontThrow);
v8::IndexedPropertyGetterCallback getter =
v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());