diff options
Diffstat (limited to 'deps/v8/src/ic/ic.cc')
-rw-r--r-- | deps/v8/src/ic/ic.cc | 286 |
1 files changed, 93 insertions, 193 deletions
diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc index 64a9f315bb..377e3df6ae 100644 --- a/deps/v8/src/ic/ic.cc +++ b/deps/v8/src/ic/ic.cc @@ -29,9 +29,7 @@ #include "src/objects/js-array-inl.h" #include "src/objects/module-inl.h" #include "src/objects/struct-inl.h" -#ifdef V8_TRACE_FEEDBACK_UPDATES #include "src/utils/ostreams.h" -#endif // V8_TRACE_FEEDBACK_UPDATES #include "src/execution/runtime-profiler.h" #include "src/objects/prototype.h" #include "src/runtime/runtime-utils.h" @@ -89,7 +87,6 @@ const char* GetModifier(KeyedAccessStoreMode mode) { void IC::TraceIC(const char* type, Handle<Object> name) { if (V8_LIKELY(!TracingFlags::is_ic_stats_enabled())) return; - if (HostIsDeoptimizedCode()) return; State new_state = (state() == NO_FEEDBACK) ? NO_FEEDBACK : nexus()->ic_state(); TraceIC(type, name, state(), new_state); @@ -126,20 +123,21 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state, return; } + JavaScriptFrameIterator it(isolate()); + JavaScriptFrame* frame = it.frame(); + JSFunction function = frame->function(); + ICStats::instance()->Begin(); ICInfo& ic_info = ICStats::instance()->Current(); ic_info.type = keyed_prefix ? "Keyed" : ""; ic_info.type += type; - Object maybe_function = - Object(Memory<Address>(fp_ + JavaScriptFrameConstants::kFunctionOffset)); - DCHECK(maybe_function.IsJSFunction()); - JSFunction function = JSFunction::cast(maybe_function); int code_offset = 0; if (function.IsInterpreted()) { - code_offset = InterpretedFrame::GetBytecodeOffset(fp()); + code_offset = InterpretedFrame::GetBytecodeOffset(frame->fp()); } else { - code_offset = static_cast<int>(pc() - function.code().InstructionStart()); + code_offset = + static_cast<int>(frame->pc() - function.code().InstructionStart()); } JavaScriptFrame::CollectFunctionAndOffsetForICStats( function, function.abstract_code(), code_offset); @@ -170,56 +168,11 @@ IC::IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot, target_maps_set_(false), slow_stub_reason_(nullptr), nexus_(vector, slot) { - // To improve the performance of the (much used) IC code, we unfold a few - // 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 = nullptr; - if (FLAG_enable_embedded_constant_pool) { - constant_pool = reinterpret_cast<Address*>( - entry + ExitFrameConstants::kConstantPoolOffset); - } - Address* pc_address = - reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); - Address fp = Memory<Address>(entry + ExitFrameConstants::kCallerFPOffset); -#ifdef DEBUG - StackFrameIterator it(isolate); - for (int i = 0; i < 1; i++) it.Advance(); - 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. - intptr_t frame_marker = - Memory<intptr_t>(fp + TypedFrameConstants::kFrameTypeOffset); - if (frame_marker == StackFrame::TypeToMarker(StackFrame::STUB)) { - fp = Memory<Address>(fp + TypedFrameConstants::kCallerFPOffset); - } - fp_ = fp; - if (FLAG_enable_embedded_constant_pool) { - constant_pool_address_ = constant_pool; - } - pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); DCHECK_IMPLIES(!vector.is_null(), kind_ == nexus_.kind()); state_ = (vector.is_null()) ? NO_FEEDBACK : nexus_.ic_state(); old_state_ = state_; } -JSFunction IC::GetHostFunction() const { - // Compute the JavaScript frame for the frame pointer of this IC - // structure. We need this to be able to find the function - // corresponding to the frame. - StackFrameIterator it(isolate()); - while (it.frame()->fp() != this->fp()) 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. - return frame->function(); -} - static void LookupForRead(LookupIterator* it, bool is_has_property) { for (; it->IsFound(); it->Next()) { switch (it->state()) { @@ -262,14 +215,14 @@ bool IC::ShouldRecomputeHandler(Handle<String> name) { // monomorphic. if (IsGlobalIC()) return true; - maybe_handler_ = nexus()->FindHandlerForMap(receiver_map()); + MaybeObjectHandle maybe_handler = nexus()->FindHandlerForMap(receiver_map()); // The current map wasn't handled yet. There's no reason to stay monomorphic, // *unless* we're moving from a deprecated map to its replacement, or // to a more general elements kind. // TODO(verwaest): Check if the current map is actually what the old map // would transition to. - if (maybe_handler_.is_null()) { + if (maybe_handler.is_null()) { if (!receiver_map()->IsJSObjectMap()) return false; Map first_map = FirstTargetMap(); if (first_map.is_null()) return false; @@ -320,27 +273,23 @@ MaybeHandle<Object> IC::ReferenceError(Handle<Name> name) { isolate(), NewReferenceError(MessageTemplate::kNotDefined, name), Object); } -// static -void IC::OnFeedbackChanged(Isolate* isolate, FeedbackNexus* nexus, - JSFunction host_function, const char* reason) { - FeedbackVector vector = nexus->vector(); - FeedbackSlot slot = nexus->slot(); - OnFeedbackChanged(isolate, vector, slot, host_function, reason); +void IC::OnFeedbackChanged(const char* reason) { + vector_set_ = true; + FeedbackVector vector = nexus()->vector(); + FeedbackSlot slot = nexus()->slot(); + OnFeedbackChanged(isolate(), vector, slot, reason); } // static void IC::OnFeedbackChanged(Isolate* isolate, FeedbackVector vector, - FeedbackSlot slot, JSFunction host_function, - const char* reason) { + FeedbackSlot slot, 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.ShortPrint(); - PrintF(" due from %d due to IC change: %s]\n", vector.profiler_ticks(), - reason); + StdoutStream os; + os << "[resetting ticks for "; + vector.shared_function_info().ShortPrint(os); + os << " from " << vector.profiler_ticks() + << " due to IC change: " << reason << "]" << std::endl; } } vector.set_profiler_ticks(0); @@ -348,7 +297,6 @@ void IC::OnFeedbackChanged(Isolate* isolate, FeedbackVector vector, #ifdef V8_TRACE_FEEDBACK_UPDATES if (FLAG_trace_feedback_updates) { int slot_count = vector.metadata().slot_count(); - StdoutStream os; if (slot.IsInvalid()) { os << "[Feedback slots in "; @@ -368,19 +316,20 @@ void IC::OnFeedbackChanged(Isolate* isolate, FeedbackVector vector, #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 - // unoptimized version for the benefit of later inlining. } -static bool MigrateDeprecated(Handle<Object> object) { +namespace { + +bool MigrateDeprecated(Isolate* isolate, Handle<Object> object) { if (!object->IsJSObject()) return false; Handle<JSObject> receiver = Handle<JSObject>::cast(object); if (!receiver->map().is_deprecated()) return false; - JSObject::MigrateInstance(Handle<JSObject>::cast(object)); + JSObject::MigrateInstance(isolate, receiver); return true; } +} // namespace + bool IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) { DCHECK_EQ(MEGAMORPHIC, new_state); DCHECK_IMPLIES(!is_keyed(), key->IsName()); @@ -389,15 +338,13 @@ bool IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) { // functions doesn't improve performance. bool changed = nexus()->ConfigureMegamorphic(key->IsName() ? PROPERTY : ELEMENT); - vector_set_ = true; - OnFeedbackChanged(isolate(), nexus(), GetHostFunction(), "Megamorphic"); + OnFeedbackChanged("Megamorphic"); return changed; } void IC::ConfigureVectorState(Handle<Map> map) { nexus()->ConfigurePremonomorphic(map); - vector_set_ = true; - OnFeedbackChanged(isolate(), nexus(), GetHostFunction(), "Premonomorphic"); + OnFeedbackChanged("Premonomorphic"); } void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, @@ -415,9 +362,7 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, nexus()->ConfigureMonomorphic(name, map, handler); } - vector_set_ = true; - OnFeedbackChanged(isolate(), nexus(), GetHostFunction(), - IsLoadGlobalIC() ? "LoadGlobal" : "Monomorphic"); + OnFeedbackChanged(IsLoadGlobalIC() ? "LoadGlobal" : "Monomorphic"); } void IC::ConfigureVectorState(Handle<Name> name, MapHandles const& maps, @@ -427,8 +372,7 @@ void IC::ConfigureVectorState(Handle<Name> name, MapHandles const& maps, if (!is_keyed()) name = Handle<Name>::null(); nexus()->ConfigurePolymorphic(name, maps, handlers); - vector_set_ = true; - OnFeedbackChanged(isolate(), nexus(), GetHostFunction(), "Polymorphic"); + OnFeedbackChanged("Polymorphic"); } MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { @@ -454,7 +398,7 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { object, name); } - if (MigrateDeprecated(object)) use_ic = false; + if (MigrateDeprecated(isolate(), object)) use_ic = false; if (state() != UNINITIALIZED) { JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate()); @@ -573,11 +517,10 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, MapHandles maps; MaybeObjectHandles handlers; - TargetMaps(&maps); + nexus()->ExtractMapsAndHandlers(&maps, &handlers); int number_of_maps = static_cast<int>(maps.size()); int deprecated_maps = 0; int handler_to_overwrite = -1; - if (!nexus()->FindHandlers(&handlers, number_of_maps)) return false; for (int i = 0; i < number_of_maps; i++) { Handle<Map> current_map = maps.at(i); @@ -642,9 +585,8 @@ void IC::UpdateMonomorphicIC(const MaybeObjectHandle& handler, void IC::CopyICToMegamorphicCache(Handle<Name> name) { MapHandles maps; MaybeObjectHandles handlers; - TargetMaps(&maps); - if (!nexus()->FindHandlers(&handlers, static_cast<int>(maps.size()))) return; - for (int i = 0; i < static_cast<int>(maps.size()); i++) { + nexus()->ExtractMapsAndHandlers(&maps, &handlers); + for (size_t i = 0; i < maps.size(); ++i) { UpdateMegamorphicCache(maps.at(i), name, handlers.at(i)); } } @@ -706,8 +648,7 @@ void IC::PatchCache(Handle<Name> name, const MaybeObjectHandle& handler) { } void LoadIC::UpdateCaches(LookupIterator* lookup) { - if (!FLAG_lazy_feedback_allocation && state() == UNINITIALIZED && - !IsLoadGlobalIC()) { + if (state() == UNINITIALIZED && !IsLoadGlobalIC()) { // 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); @@ -763,17 +704,6 @@ void IC::UpdateMegamorphicCache(Handle<Map> map, Handle<Name> name, } } -void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) { - DCHECK_EQ(LookupIterator::ACCESSOR, lookup->state()); - if (V8_LIKELY(!TracingFlags::is_runtime_stats_enabled())) return; - if (IsAnyLoad() || IsAnyHas()) { - TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Accessor); - } else { - DCHECK(IsAnyStore()); - TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Accessor); - } -} - Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) { Handle<Object> receiver = lookup->GetReceiver(); ReadOnlyRoots roots(isolate()); @@ -1035,7 +965,8 @@ bool KeyedLoadIC::CanChangeToAllowOutOfBounds(Handle<Map> receiver_map) { 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. + DCHECK(receiver_map->instance_type() != + JS_PRIMITIVE_WRAPPER_TYPE); // Checked by caller. MapHandles target_receiver_maps; TargetMaps(&target_receiver_maps); @@ -1046,8 +977,8 @@ void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver, for (Handle<Map> map : target_receiver_maps) { if (map.is_null()) continue; - if (map->instance_type() == JS_VALUE_TYPE) { - set_slow_stub_reason("JSValue"); + if (map->instance_type() == JS_PRIMITIVE_WRAPPER_TYPE) { + set_slow_stub_reason("JSPrimitiveWrapper"); return; } if (map->instance_type() == JS_PROXY_TYPE) { @@ -1091,7 +1022,8 @@ void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver, // If the maximum number of receiver maps has been exceeded, use the generic // version of the IC. - if (target_receiver_maps.size() > kMaxKeyedPolymorphism) { + if (static_cast<int>(target_receiver_maps.size()) > + FLAG_max_polymorphic_map_count) { set_slow_stub_reason("max polymorph exceeded"); return; } @@ -1228,7 +1160,9 @@ namespace { bool ConvertKeyToIndex(Handle<Object> receiver, Handle<Object> key, uint32_t* index, InlineCacheState state) { if (!FLAG_use_ic || state == NO_FEEDBACK) return false; - if (receiver->IsAccessCheckNeeded() || receiver->IsJSValue()) return false; + if (receiver->IsAccessCheckNeeded() || receiver->IsJSPrimitiveWrapper()) { + return false; + } // For regular JSReceiver or String receivers, the {key} must be a positive // array index. @@ -1299,7 +1233,7 @@ MaybeHandle<Object> KeyedLoadIC::RuntimeLoad(Handle<Object> object, MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, Handle<Object> key) { - if (MigrateDeprecated(object)) { + if (MigrateDeprecated(isolate(), object)) { return RuntimeLoad(object, key); } @@ -1459,7 +1393,7 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, StoreOrigin store_origin) { // TODO(verwaest): Let SetProperty do the migration, since storing a property // might deprecate the current map again, if value does not fit. - if (MigrateDeprecated(object)) { + if (MigrateDeprecated(isolate(), object)) { Handle<Object> result; ASSIGN_RETURN_ON_EXCEPTION( isolate(), result, Object::SetProperty(isolate(), object, name, value), @@ -1779,9 +1713,9 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, } for (Handle<Map> map : target_receiver_maps) { - if (!map.is_null() && map->instance_type() == JS_VALUE_TYPE) { + if (!map.is_null() && map->instance_type() == JS_PRIMITIVE_WRAPPER_TYPE) { DCHECK(!IsStoreInArrayLiteralICKind(kind())); - set_slow_stub_reason("JSValue"); + set_slow_stub_reason("JSPrimitiveWrapper"); return; } } @@ -1836,7 +1770,10 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, // If the maximum number of receiver maps has been exceeded, use the // megamorphic version of the IC. - if (target_receiver_maps.size() > kMaxKeyedPolymorphism) return; + if (static_cast<int>(target_receiver_maps.size()) > + FLAG_max_polymorphic_map_count) { + return; + } // Make sure all polymorphic handlers have the same store mode, otherwise the // megamorphic stub must be used. @@ -2001,13 +1938,9 @@ bool MayHaveTypedArrayInPrototypeChain(Handle<JSObject> object) { KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver, uint32_t index) { bool oob_access = IsOutOfBoundsAccess(receiver, index); // Don't consider this a growing store if the store would send the receiver to - // dictionary mode. Also make sure we don't consider this a growing store if - // there's any JSTypedArray in the {receiver}'s prototype chain, since that - // prototype is going to swallow all stores that are out-of-bounds for said - // prototype, and we just let the runtime deal with the complexity of this. + // dictionary mode. bool allow_growth = receiver->IsJSArray() && oob_access && - !receiver->WouldConvertToSlowElements(index) && - !MayHaveTypedArrayInPrototypeChain(receiver); + !receiver->WouldConvertToSlowElements(index); if (allow_growth) { return STORE_AND_GROW_HANDLE_COW; } @@ -2024,7 +1957,7 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, Handle<Object> value) { // TODO(verwaest): Let SetProperty do the migration, since storing a property // might deprecate the current map again, if value does not fit. - if (MigrateDeprecated(object)) { + if (MigrateDeprecated(isolate(), object)) { Handle<Object> result; ASSIGN_RETURN_ON_EXCEPTION( isolate(), result, @@ -2109,6 +2042,16 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, if (!old_receiver_map.is_null()) { if (is_arguments) { set_slow_stub_reason("arguments receiver"); + } else if (object->IsJSArray() && IsGrowStoreMode(store_mode) && + JSArray::HasReadOnlyLength(Handle<JSArray>::cast(object))) { + set_slow_stub_reason("array has read only length"); + } else if (object->IsJSArray() && MayHaveTypedArrayInPrototypeChain( + Handle<JSObject>::cast(object))) { + // Make sure we don't handle this in IC if there's any JSTypedArray in + // the {receiver}'s prototype chain, since that prototype is going to + // swallow all stores that are out-of-bounds for said prototype, and we + // just let the runtime deal with the complexity of this. + set_slow_stub_reason("typed array in the prototype chain of an Array"); } else if (key_is_valid_index) { if (old_receiver_map->is_abandoned_prototype_map()) { set_slow_stub_reason("receiver with prototype map"); @@ -2160,7 +2103,8 @@ void StoreInArrayLiteralIC::Store(Handle<JSArray> array, Handle<Object> index, DCHECK(!array->map().IsMapInArrayPrototypeChain(isolate())); DCHECK(index->IsNumber()); - if (!FLAG_use_ic || state() == NO_FEEDBACK || MigrateDeprecated(array)) { + if (!FLAG_use_ic || state() == NO_FEEDBACK || + MigrateDeprecated(isolate(), array)) { StoreOwnElement(isolate(), array, index, value); TraceIC("StoreInArrayLiteralIC", index); return; @@ -2585,10 +2529,9 @@ static bool CanFastCloneObject(Handle<Map> map) { return true; } -static Handle<Map> FastCloneObjectMap(Isolate* isolate, - Handle<HeapObject> source, int flags) { - Handle<Map> source_map(source->map(), isolate); - SLOW_DCHECK(source->IsNullOrUndefined() || CanFastCloneObject(source_map)); +static Handle<Map> FastCloneObjectMap(Isolate* isolate, Handle<Map> source_map, + int flags) { + SLOW_DCHECK(CanFastCloneObject(source_map)); Handle<JSFunction> constructor(isolate->native_context()->object_function(), isolate); DCHECK(constructor->has_initial_map()); @@ -2613,9 +2556,10 @@ static Handle<Map> FastCloneObjectMap(Isolate* isolate, Map::SetPrototype(isolate, map, isolate->factory()->null_value()); } - if (source->IsNullOrUndefined() || !source_map->NumberOfOwnDescriptors()) { + if (source_map->NumberOfOwnDescriptors() == 0) { return map; } + DCHECK(!source_map->IsNullOrUndefinedMap()); if (map.is_identical_to(initial_map)) { map = Map::Copy(isolate, map, "InitializeClonedDescriptors"); @@ -2640,7 +2584,7 @@ static Handle<Map> FastCloneObjectMap(Isolate* isolate, } static MaybeHandle<JSObject> CloneObjectSlowPath(Isolate* isolate, - Handle<HeapObject> source, + Handle<Object> source, int flags) { Handle<JSObject> new_object; if (flags & ObjectLiteral::kHasNullPrototype) { @@ -2664,35 +2608,31 @@ static MaybeHandle<JSObject> CloneObjectSlowPath(Isolate* isolate, RUNTIME_FUNCTION(Runtime_CloneObjectIC_Miss) { HandleScope scope(isolate); DCHECK_EQ(4, args.length()); - Handle<HeapObject> source = args.at<HeapObject>(0); + Handle<Object> source = args.at<Object>(0); int flags = args.smi_at(1); - MigrateDeprecated(source); - - FeedbackSlot slot = FeedbackVector::ToSlot(args.smi_at(2)); - Handle<HeapObject> maybe_vector = args.at<HeapObject>(3); - if (maybe_vector->IsUndefined()) { - RETURN_RESULT_OR_FAILURE(isolate, - CloneObjectSlowPath(isolate, source, flags)); - } - - DCHECK(maybe_vector->IsFeedbackVector()); - Handle<FeedbackVector> vector = Handle<FeedbackVector>::cast(maybe_vector); - - FeedbackNexus nexus(vector, slot); - Handle<Map> source_map(source->map(), isolate); + if (!MigrateDeprecated(isolate, source)) { + FeedbackSlot slot = FeedbackVector::ToSlot(args.smi_at(2)); + Handle<HeapObject> maybe_vector = args.at<HeapObject>(3); + if (maybe_vector->IsFeedbackVector()) { + FeedbackNexus nexus(Handle<FeedbackVector>::cast(maybe_vector), slot); + if (!source->IsSmi() && !nexus.IsMegamorphic()) { + Handle<Map> source_map(Handle<HeapObject>::cast(source)->map(), + isolate); + if (CanFastCloneObject(source_map)) { + Handle<Map> target_map = + FastCloneObjectMap(isolate, source_map, flags); + nexus.ConfigureCloneObject(source_map, target_map); + return *target_map; + } - if (!CanFastCloneObject(source_map) || nexus.IsMegamorphic()) { - // Migrate to slow mode if needed. - nexus.ConfigureMegamorphic(); - RETURN_RESULT_OR_FAILURE(isolate, - CloneObjectSlowPath(isolate, source, flags)); + nexus.ConfigureMegamorphic(); + } + } } - Handle<Map> result_map = FastCloneObjectMap(isolate, source, flags); - nexus.ConfigureCloneObject(source_map, result_map); - - return *result_map; + RETURN_RESULT_OR_FAILURE(isolate, + CloneObjectSlowPath(isolate, source, flags)); } RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) { @@ -2718,46 +2658,6 @@ RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) { return *value; } -RUNTIME_FUNCTION(Runtime_LoadCallbackProperty) { - Handle<JSObject> receiver = args.at<JSObject>(0); - Handle<JSObject> holder = args.at<JSObject>(1); - Handle<AccessorInfo> info = args.at<AccessorInfo>(2); - Handle<Name> name = args.at<Name>(3); - HandleScope scope(isolate); - - DCHECK(info->IsCompatibleReceiver(*receiver)); - - PropertyCallbackArguments custom_args(isolate, info->data(), *receiver, - *holder, Just(kThrowOnError)); - Handle<Object> result = custom_args.CallAccessorGetter(info, name); - RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); - if (result.is_null()) return ReadOnlyRoots(isolate).undefined_value(); - return *result; -} - -RUNTIME_FUNCTION(Runtime_LoadAccessorProperty) { - HandleScope scope(isolate); - DCHECK_EQ(args.length(), 3); - Handle<JSObject> receiver = args.at<JSObject>(0); - int handler_kind = args.smi_at(1); - Handle<CallHandlerInfo> call_handler_info = args.at<CallHandlerInfo>(2); - - Object holder = *receiver; - if (handler_kind == LoadHandler::kApiGetterHolderIsPrototype) { - holder = receiver->map().prototype(); - } else { - DCHECK_EQ(handler_kind, LoadHandler::kApiGetter); - } - - // Call the accessor without additional arguments. - FunctionCallbackArguments custom(isolate, call_handler_info->data(), - *receiver, holder, HeapObject(), nullptr, 0); - Handle<Object> result_handle = custom.Call(*call_handler_info); - RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); - if (result_handle.is_null()) return ReadOnlyRoots(isolate).undefined_value(); - return *result_handle; -} - /** * Loads a property with an interceptor performing post interceptor * lookup if interceptor failed. |