diff options
Diffstat (limited to 'deps/v8/src/objects.cc')
-rw-r--r-- | deps/v8/src/objects.cc | 613 |
1 files changed, 351 insertions, 262 deletions
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index bd876e67d7..f8c55e57a6 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -73,6 +73,7 @@ #include "src/trap-handler/trap-handler.h" #include "src/unicode-cache-inl.h" #include "src/utils-inl.h" +#include "src/wasm/wasm-engine.h" #include "src/wasm/wasm-objects.h" #include "src/zone/zone.h" @@ -1163,7 +1164,7 @@ MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate, Object); } // 5. Let target be the value of the [[ProxyTarget]] internal slot of O. - Handle<JSReceiver> target(proxy->target(), isolate); + Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); // 6. Let trap be ? GetMethod(handler, "get"). Handle<Object> trap; ASSIGN_RETURN_ON_EXCEPTION( @@ -1536,7 +1537,7 @@ MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) { NewTypeError(MessageTemplate::kProxyRevoked, trap_name), Object); } - Handle<JSReceiver> target(proxy->target(), isolate); + Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); // 5. Let trap be ? GetMethod(handler, "getPrototypeOf"). @@ -1605,9 +1606,7 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) { Object); } - v8::AccessorNameGetterCallback call_fun = - v8::ToCData<v8::AccessorNameGetterCallback>(info->getter()); - if (call_fun == nullptr) return isolate->factory()->undefined_value(); + if (!info->has_getter()) return isolate->factory()->undefined_value(); if (info->is_sloppy() && !receiver->IsJSReceiver()) { ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver, @@ -1617,14 +1616,15 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) { PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder, kDontThrow); - Handle<Object> result = args.Call(call_fun, name); + Handle<Object> result = args.CallAccessorGetter(info, name); RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); if (result.is_null()) return isolate->factory()->undefined_value(); Handle<Object> reboxed_result = handle(*result, isolate); if (info->replace_on_access() && receiver->IsJSReceiver()) { - args.Call(reinterpret_cast<GenericNamedPropertySetterCallback>( - &Accessors::ReconfigureToDataProperty), - name, result); + args.CallNamedSetterCallback( + reinterpret_cast<GenericNamedPropertySetterCallback>( + &Accessors::ReconfigureToDataProperty), + name, result); RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); } return reboxed_result; @@ -1733,7 +1733,7 @@ Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it, PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder, should_throw); - Handle<Object> result = args.Call(call_fun, name, value); + Handle<Object> result = args.CallNamedSetterCallback(call_fun, name, value); // In the case of AccessorNameSetterCallback, we know that the result value // cannot have been set, so the result of Call will be null. In the case of // AccessorNameBooleanSetterCallback, the result will either be null @@ -1853,20 +1853,9 @@ MaybeHandle<Object> GetPropertyWithInterceptorInternal( *holder, kDontThrow); if (it->IsElement()) { - uint32_t index = it->index(); - v8::IndexedPropertyGetterCallback getter = - v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); - result = args.Call(getter, index); + result = args.CallIndexedGetter(interceptor, it->index()); } else { - Handle<Name> name = it->name(); - DCHECK(!name->IsPrivate()); - - DCHECK_IMPLIES(name->IsSymbol(), interceptor->can_intercept_symbols()); - - v8::GenericNamedPropertyGetterCallback getter = - v8::ToCData<v8::GenericNamedPropertyGetterCallback>( - interceptor->getter()); - result = args.Call(getter, name); + result = args.CallNamedGetter(interceptor, it->name()); } RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); @@ -1898,17 +1887,9 @@ Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal( if (!interceptor->query()->IsUndefined(isolate)) { Handle<Object> result; if (it->IsElement()) { - uint32_t index = it->index(); - v8::IndexedPropertyQueryCallback query = - v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); - result = args.Call(query, index); + result = args.CallIndexedQuery(interceptor, it->index()); } else { - Handle<Name> name = it->name(); - DCHECK(!name->IsPrivate()); - v8::GenericNamedPropertyQueryCallback query = - v8::ToCData<v8::GenericNamedPropertyQueryCallback>( - interceptor->query()); - result = args.Call(query, name); + result = args.CallNamedQuery(interceptor, it->name()); } if (!result.is_null()) { int32_t value; @@ -1919,17 +1900,9 @@ Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal( // TODO(verwaest): Use GetPropertyWithInterceptor? Handle<Object> result; if (it->IsElement()) { - uint32_t index = it->index(); - v8::IndexedPropertyGetterCallback getter = - v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); - result = args.Call(getter, index); + result = args.CallIndexedGetter(interceptor, it->index()); } else { - Handle<Name> name = it->name(); - DCHECK(!name->IsPrivate()); - v8::GenericNamedPropertyGetterCallback getter = - v8::ToCData<v8::GenericNamedPropertyGetterCallback>( - interceptor->getter()); - result = args.Call(getter, name); + result = args.CallNamedGetter(interceptor, it->name()); } if (!result.is_null()) return Just(DONT_ENUM); } @@ -1960,22 +1933,11 @@ Maybe<bool> SetPropertyWithInterceptorInternal( *holder, should_throw); if (it->IsElement()) { - uint32_t index = it->index(); - v8::IndexedPropertySetterCallback setter = - v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter()); // TODO(neis): In the future, we may want to actually return the // interceptor's result, which then should be a boolean. - result = !args.Call(setter, index, value).is_null(); + result = !args.CallIndexedSetter(interceptor, it->index(), value).is_null(); } else { - Handle<Name> name = it->name(); - DCHECK(!name->IsPrivate()); - - DCHECK_IMPLIES(name->IsSymbol(), interceptor->can_intercept_symbols()); - - v8::GenericNamedPropertySetterCallback setter = - v8::ToCData<v8::GenericNamedPropertySetterCallback>( - interceptor->setter()); - result = !args.Call(setter, name, value).is_null(); + result = !args.CallNamedSetter(interceptor, it->name(), value).is_null(); } RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); @@ -2025,20 +1987,11 @@ Maybe<bool> DefinePropertyWithInterceptorInternal( } if (it->IsElement()) { - uint32_t index = it->index(); - v8::IndexedPropertyDefinerCallback definer = - v8::ToCData<v8::IndexedPropertyDefinerCallback>(interceptor->definer()); - result = !args.Call(definer, index, *descriptor).is_null(); + result = !args.CallIndexedDefiner(interceptor, it->index(), *descriptor) + .is_null(); } else { - Handle<Name> name = it->name(); - DCHECK(!name->IsPrivate()); - - DCHECK_IMPLIES(name->IsSymbol(), interceptor->can_intercept_symbols()); - - v8::GenericNamedPropertyDefinerCallback definer = - v8::ToCData<v8::GenericNamedPropertyDefinerCallback>( - interceptor->definer()); - result = !args.Call(definer, name, *descriptor).is_null(); + result = + !args.CallNamedDefiner(interceptor, it->name(), *descriptor).is_null(); } RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); @@ -2163,11 +2116,13 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object, uint32_t hash = name->Hash(); if (object->IsJSGlobalObject()) { - Handle<JSGlobalObject> global_obj(JSGlobalObject::cast(*object)); + Handle<JSGlobalObject> global_obj = Handle<JSGlobalObject>::cast(object); Handle<GlobalDictionary> dictionary(global_obj->global_dictionary()); int entry = dictionary->FindEntry(isolate, name, hash); if (entry == GlobalDictionary::kNotFound) { + DCHECK_IMPLIES(global_obj->map()->is_prototype_map(), + Map::IsPrototypeChainInvalidated(global_obj->map())); auto cell = isolate->factory()->NewPropertyCell(name); cell->set_value(*value); auto cell_type = value->IsUndefined(isolate) @@ -2187,6 +2142,8 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object, int entry = dictionary->FindEntry(name); if (entry == NameDictionary::kNotFound) { + DCHECK_IMPLIES(object->map()->is_prototype_map(), + Map::IsPrototypeChainInvalidated(object->map())); dictionary = NameDictionary::Add(dictionary, name, value, details); object->SetProperties(*dictionary); } else { @@ -2613,7 +2570,7 @@ bool Object::IterationHasObservableEffects() { JSArray* array = JSArray::cast(this); Isolate* isolate = array->GetIsolate(); -#if defined(DEBUG) || defined(ENABLE_SLOWFAST_SWITCH) +#ifdef V8_ENABLE_FORCE_SLOW_PATH if (isolate->force_slow_path()) return true; #endif @@ -3280,7 +3237,10 @@ VisitorId Map::GetVisitorId(Map* map) { if (instance_type == ALLOCATION_SITE_TYPE) { return kVisitAllocationSite; } + return kVisitStruct; + case LOAD_HANDLER_TYPE: + case STORE_HANDLER_TYPE: return kVisitStruct; default: @@ -4213,6 +4173,9 @@ void MigrateFastToSlow(Handle<JSObject> object, Handle<Map> new_map, // JSGlobalProxy must never be normalized DCHECK(!object->IsJSGlobalProxy()); + DCHECK_IMPLIES(new_map->is_prototype_map(), + Map::IsPrototypeChainInvalidated(*new_map)); + Isolate* isolate = object->GetIsolate(); HandleScope scope(isolate); Handle<Map> map(object->map()); @@ -4474,7 +4437,10 @@ void Map::DeprecateTransitionTree() { transitions.GetTarget(i)->DeprecateTransitionTree(); } DCHECK(!constructor_or_backpointer()->IsFunctionTemplateInfo()); - deprecate(); + set_is_deprecated(true); + if (FLAG_trace_maps) { + LOG(GetIsolate(), MapEvent("Deprecate", this, nullptr)); + } dependent_code()->DeoptimizeDependentCodeGroup( GetIsolate(), DependentCode::kTransitionGroup); NotifyLeafMapLayoutChange(); @@ -5547,7 +5513,13 @@ Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, void JSProxy::Revoke(Handle<JSProxy> proxy) { Isolate* isolate = proxy->GetIsolate(); - if (!proxy->IsRevoked()) proxy->set_handler(isolate->heap()->null_value()); + // ES#sec-proxy-revocation-functions + if (!proxy->IsRevoked()) { + // 5. Set p.[[ProxyTarget]] to null. + proxy->set_target(isolate->heap()->null_value()); + // 6. Set p.[[ProxyHandler]] to null. + proxy->set_handler(isolate->heap()->null_value()); + } DCHECK(proxy->IsRevoked()); } @@ -5563,7 +5535,7 @@ Maybe<bool> JSProxy::IsArray(Handle<JSProxy> proxy) { isolate->factory()->NewStringFromAsciiChecked("IsArray"))); return Nothing<bool>(); } - object = handle(proxy->target(), isolate); + object = handle(JSReceiver::cast(proxy->target()), isolate); if (object->IsJSArray()) return Just(true); if (!object->IsJSProxy()) return Just(false); } @@ -5588,7 +5560,7 @@ Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy, return Nothing<bool>(); } // 5. Let target be the value of the [[ProxyTarget]] internal slot of O. - Handle<JSReceiver> target(proxy->target(), isolate); + Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); // 6. Let trap be ? GetMethod(handler, "has"). Handle<Object> trap; ASSIGN_RETURN_ON_EXCEPTION_VALUE( @@ -5661,7 +5633,7 @@ Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name, *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); return Nothing<bool>(); } - Handle<JSReceiver> target(proxy->target(), isolate); + Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); Handle<Object> trap; @@ -5712,7 +5684,7 @@ Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy, *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); return Nothing<bool>(); } - Handle<JSReceiver> target(proxy->target(), isolate); + Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); Handle<Object> trap; @@ -5986,7 +5958,7 @@ void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { void JSObject::MigrateInstance(Handle<JSObject> object) { Handle<Map> original_map(object->map()); Handle<Map> map = Map::Update(original_map); - map->set_migration_target(true); + map->set_is_migration_target(true); MigrateToMap(object, map); if (FLAG_trace_migration) { object->PrintInstanceMigration(stdout, *original_map, *map); @@ -6300,7 +6272,7 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object, Handle<Map> new_map = Map::CopyDropDescriptors(old_map); new_map->set_may_have_interesting_symbols(new_map->has_named_interceptor() || new_map->is_access_check_needed()); - new_map->set_dictionary_map(false); + new_map->set_is_dictionary_map(false); NotifyMapChange(old_map, new_map, isolate); @@ -6626,19 +6598,9 @@ Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it, *holder, should_throw); Handle<Object> result; if (it->IsElement()) { - uint32_t index = it->index(); - v8::IndexedPropertyDeleterCallback deleter = - v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter()); - result = args.Call(deleter, index); + result = args.CallIndexedDeleter(interceptor, it->index()); } else { - DCHECK_IMPLIES(it->name()->IsSymbol(), - interceptor->can_intercept_symbols()); - Handle<Name> name = it->name(); - DCHECK(!name->IsPrivate()); - v8::GenericNamedPropertyDeleterCallback deleter = - v8::ToCData<v8::GenericNamedPropertyDeleterCallback>( - interceptor->deleter()); - result = args.Call(deleter, name); + result = args.CallNamedDeleter(interceptor, it->name()); } RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); @@ -7526,7 +7488,7 @@ Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy, return Nothing<bool>(); } // 5. Let target be the value of the [[ProxyTarget]] internal slot of O. - Handle<JSReceiver> target(proxy->target(), isolate); + Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); // 6. Let trap be ? GetMethod(handler, "defineProperty"). Handle<Object> trap; ASSIGN_RETURN_ON_EXCEPTION_VALUE( @@ -7690,19 +7652,9 @@ Maybe<bool> GetPropertyDescriptorWithInterceptor(LookupIterator* it, PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, *holder, kDontThrow); if (it->IsElement()) { - uint32_t index = it->index(); - v8::IndexedPropertyDescriptorCallback descriptorCallback = - v8::ToCData<v8::IndexedPropertyDescriptorCallback>( - interceptor->descriptor()); - - result = args.Call(descriptorCallback, index); + result = args.CallIndexedDescriptor(interceptor, it->index()); } else { - Handle<Name> name = it->name(); - DCHECK(!name->IsPrivate()); - v8::GenericNamedPropertyDescriptorCallback descriptorCallback = - v8::ToCData<v8::GenericNamedPropertyDescriptorCallback>( - interceptor->descriptor()); - result = args.Call(descriptorCallback, name); + result = args.CallNamedDescriptor(interceptor, it->name()); } if (!result.is_null()) { // Request successfully intercepted, try to set the property @@ -7809,7 +7761,7 @@ Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate, return Nothing<bool>(); } // 5. Let target be the value of the [[ProxyTarget]] internal slot of O. - Handle<JSReceiver> target(proxy->target(), isolate); + Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor"). Handle<Object> trap; ASSIGN_RETURN_ON_EXCEPTION_VALUE( @@ -8261,7 +8213,7 @@ Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy, *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); return Nothing<bool>(); } - Handle<JSReceiver> target(proxy->target(), isolate); + Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); Handle<Object> trap; @@ -8369,7 +8321,7 @@ Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) { *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); return Nothing<bool>(); } - Handle<JSReceiver> target(proxy->target(), isolate); + Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); Handle<Object> trap; @@ -8839,9 +8791,10 @@ MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries( MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate, Handle<JSReceiver> object, PropertyFilter filter, + bool try_fast_path, bool get_entries) { Handle<FixedArray> values_or_entries; - if (filter == ENUMERABLE_STRINGS) { + if (try_fast_path && filter == ENUMERABLE_STRINGS) { Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries( isolate, object, get_entries, &values_or_entries); if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>(); @@ -8894,13 +8847,17 @@ MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate, } MaybeHandle<FixedArray> JSReceiver::GetOwnValues(Handle<JSReceiver> object, - PropertyFilter filter) { - return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, false); + PropertyFilter filter, + bool try_fast_path) { + return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, + try_fast_path, false); } MaybeHandle<FixedArray> JSReceiver::GetOwnEntries(Handle<JSReceiver> object, - PropertyFilter filter) { - return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, true); + PropertyFilter filter, + bool try_fast_path) { + return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, + try_fast_path, true); } bool Map::DictionaryElementsInPrototypeChainOnly() { @@ -9077,13 +9034,13 @@ Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size, result->set_bit_field(map->bit_field()); result->set_bit_field2(map->bit_field2()); int new_bit_field3 = map->bit_field3(); - new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); + new_bit_field3 = OwnsDescriptorsBit::update(new_bit_field3, true); new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCacheSentinel); - new_bit_field3 = Deprecated::update(new_bit_field3, false); + new_bit_field3 = IsDeprecatedBit::update(new_bit_field3, false); if (!map->is_dictionary_map()) { - new_bit_field3 = IsUnstable::update(new_bit_field3, false); + new_bit_field3 = IsUnstableBit::update(new_bit_field3, false); } result->set_bit_field3(new_bit_field3); return result; @@ -9164,8 +9121,8 @@ Handle<Map> Map::CopyNormalized(Handle<Map> map, // Clear the unused_property_fields explicitly as this field should not // be accessed for normalized maps. result->SetInObjectUnusedPropertyFields(0); - result->set_dictionary_map(true); - result->set_migration_target(false); + result->set_is_dictionary_map(true); + result->set_is_migration_target(false); result->set_may_have_interesting_symbols(true); result->set_construction_counter(kNoSlackTracking); @@ -9184,7 +9141,7 @@ Handle<Map> Map::CopyNormalized(Handle<Map> map, // static Handle<Map> Map::TransitionToImmutableProto(Handle<Map> map) { Handle<Map> new_map = Map::Copy(map, "ImmutablePrototype"); - new_map->set_immutable_proto(true); + new_map->set_is_immutable_proto(true); return new_map; } @@ -9723,8 +9680,8 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, bool* created_new_map) { RuntimeCallTimerScope stats_scope( *map, map->is_prototype_map() - ? &RuntimeCallStats::PrototypeMap_TransitionToDataProperty - : &RuntimeCallStats::Map_TransitionToDataProperty); + ? RuntimeCallCounterId::kPrototypeMap_TransitionToDataProperty + : RuntimeCallCounterId::kMap_TransitionToDataProperty); DCHECK(name->IsUniqueName()); DCHECK(!map->is_dictionary_map()); @@ -9839,8 +9796,8 @@ Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map, RuntimeCallTimerScope stats_scope( isolate, map->is_prototype_map() - ? &RuntimeCallStats::PrototypeMap_TransitionToAccessorProperty - : &RuntimeCallStats::Map_TransitionToAccessorProperty); + ? RuntimeCallCounterId::kPrototypeMap_TransitionToAccessorProperty + : RuntimeCallCounterId::kMap_TransitionToAccessorProperty); // At least one of the accessors needs to be a new value. DCHECK(!getter->IsNull(isolate) || !setter->IsNull(isolate)); @@ -10291,8 +10248,10 @@ Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1, // static Handle<ArrayList> ArrayList::New(Isolate* isolate, int size) { - Handle<ArrayList> result = Handle<ArrayList>::cast( - isolate->factory()->NewFixedArray(size + kFirstIndex)); + Handle<FixedArray> fixed_array = + isolate->factory()->NewFixedArray(size + kFirstIndex); + fixed_array->set_map_no_write_barrier(isolate->heap()->array_list_map()); + Handle<ArrayList> result = Handle<ArrayList>::cast(fixed_array); result->SetLength(0); return result; } @@ -10331,10 +10290,13 @@ Handle<FixedArray> EnsureSpaceInFixedArray(Handle<FixedArray> array, // static Handle<ArrayList> ArrayList::EnsureSpace(Handle<ArrayList> array, int length) { const bool empty = (array->length() == 0); - auto ret = Handle<ArrayList>::cast( - EnsureSpaceInFixedArray(array, kFirstIndex + length)); - if (empty) ret->SetLength(0); - return ret; + auto ret = EnsureSpaceInFixedArray(array, kFirstIndex + length); + if (empty) { + ret->set_map_no_write_barrier(array->GetHeap()->array_list_map()); + + Handle<ArrayList>::cast(ret)->SetLength(0); + } + return Handle<ArrayList>::cast(ret); } Handle<RegExpMatchInfo> RegExpMatchInfo::ReserveCaptures( @@ -10710,7 +10672,7 @@ Handle<Object> String::ToNumber(Handle<String> subject) { // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit // or the 'I' character ('Infinity'). All of that have codes not greater // than '9' except 'I' and . - if (data[start_pos] != 'I' && data[start_pos] != 0xa0) { + if (data[start_pos] != 'I' && data[start_pos] != 0xA0) { return isolate->factory()->nan_value(); } } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) { @@ -12551,15 +12513,19 @@ bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) { return true; } +namespace { -static void InvalidatePrototypeChainsInternal(Map* map) { +// This function must be kept in sync with +// AccessorAssembler::InvalidateValidityCellIfPrototype() which does pre-checks +// before jumping here. +PrototypeInfo* InvalidateOnePrototypeValidityCellInternal(Map* map) { DCHECK(map->is_prototype_map()); if (FLAG_trace_prototype_users) { PrintF("Invalidating prototype map %p 's cell\n", reinterpret_cast<void*>(map)); } Object* maybe_proto_info = map->prototype_info(); - if (!maybe_proto_info->IsPrototypeInfo()) return; + if (!maybe_proto_info->IsPrototypeInfo()) return nullptr; PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info); Object* maybe_cell = proto_info->validity_cell(); if (maybe_cell->IsCell()) { @@ -12567,6 +12533,12 @@ static void InvalidatePrototypeChainsInternal(Map* map) { Cell* cell = Cell::cast(maybe_cell); cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid)); } + return proto_info; +} + +void InvalidatePrototypeChainsInternal(Map* map) { + PrototypeInfo* proto_info = InvalidateOnePrototypeValidityCellInternal(map); + if (proto_info == nullptr) return; WeakFixedArray::Iterator iterator(proto_info->prototype_users()); // For now, only maps register themselves as users. @@ -12577,13 +12549,27 @@ static void InvalidatePrototypeChainsInternal(Map* map) { } } +} // namespace // static -void JSObject::InvalidatePrototypeChains(Map* map) { +Map* JSObject::InvalidatePrototypeChains(Map* map) { DisallowHeapAllocation no_gc; InvalidatePrototypeChainsInternal(map); + return map; } +// We also invalidate global objects validity cell when a new lexical +// environment variable is added. This is necessary to ensure that +// Load/StoreGlobalIC handlers that load/store from global object's prototype +// get properly invalidated. +// Note, that the normal Load/StoreICs that load/store through the global object +// in the prototype chain are not affected by appearance of a new lexical +// variable and therefore we don't propagate invalidation down. +// static +void JSObject::InvalidatePrototypeValidityCell(JSGlobalObject* global) { + DisallowHeapAllocation no_gc; + InvalidateOnePrototypeValidityCellInternal(global->map()); +} // static Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype, @@ -12662,6 +12648,21 @@ Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, } // static +bool Map::IsPrototypeChainInvalidated(Map* map) { + DCHECK(map->is_prototype_map()); + Object* maybe_proto_info = map->prototype_info(); + if (maybe_proto_info->IsPrototypeInfo()) { + PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info); + Object* maybe_cell = proto_info->validity_cell(); + if (maybe_cell->IsCell()) { + Cell* cell = Cell::cast(maybe_cell); + return cell->value() == Smi::FromInt(Map::kPrototypeChainInvalid); + } + } + return true; +} + +// static Handle<WeakCell> Map::GetOrCreatePrototypeWeakCell(Handle<JSReceiver> prototype, Isolate* isolate) { DCHECK(!prototype.is_null()); @@ -12688,7 +12689,8 @@ Handle<WeakCell> Map::GetOrCreatePrototypeWeakCell(Handle<JSReceiver> prototype, // static void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype, bool enable_prototype_setup_mode) { - RuntimeCallTimerScope stats_scope(*map, &RuntimeCallStats::Map_SetPrototype); + RuntimeCallTimerScope stats_scope(*map, + RuntimeCallCounterId::kMap_SetPrototype); bool is_hidden = false; if (prototype->IsJSObject()) { @@ -12815,7 +12817,7 @@ void JSFunction::SetPrototype(Handle<JSFunction> function, JSObject::MigrateToMap(function, new_map); new_map->SetConstructor(*value); - new_map->set_non_instance_prototype(true); + new_map->set_has_non_instance_prototype(true); FunctionKind kind = function->shared()->kind(); Handle<Context> native_context(function->context()->native_context()); @@ -12829,7 +12831,7 @@ void JSFunction::SetPrototype(Handle<JSFunction> function, isolate); } else { construct_prototype = Handle<JSReceiver>::cast(value); - function->map()->set_non_instance_prototype(false); + function->map()->set_has_non_instance_prototype(false); } SetInstancePrototype(isolate, function, construct_prototype); @@ -12976,6 +12978,56 @@ void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { map->StartInobjectSlackTracking(); } +namespace { +bool FastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target, + Handle<JSFunction> constructor, + Handle<Map> constructor_initial_map) { + // Check that |function|'s initial map still in sync with the |constructor|, + // otherwise we must create a new initial map for |function|. + if (new_target->has_initial_map() && + new_target->initial_map()->GetConstructor() == *constructor) { + DCHECK(new_target->instance_prototype()->IsJSReceiver()); + return true; + } + InstanceType instance_type = constructor_initial_map->instance_type(); + DCHECK(CanSubclassHaveInobjectProperties(instance_type)); + // Create a new map with the size and number of in-object properties + // suggested by |function|. + + // Link initial map and constructor function if the new.target is actually a + // subclass constructor. + if (!IsDerivedConstructor(new_target->shared()->kind())) return false; + + int instance_size; + int in_object_properties; + int embedder_fields = + JSObject::GetEmbedderFieldCount(*constructor_initial_map); + bool success = JSFunction::CalculateInstanceSizeForDerivedClass( + new_target, instance_type, embedder_fields, &instance_size, + &in_object_properties); + + Handle<Map> map; + if (success) { + int pre_allocated = constructor_initial_map->GetInObjectProperties() - + constructor_initial_map->UnusedPropertyFields(); + CHECK_LE(constructor_initial_map->UsedInstanceSize(), instance_size); + int unused_property_fields = in_object_properties - pre_allocated; + map = Map::CopyInitialMap(constructor_initial_map, instance_size, + in_object_properties, unused_property_fields); + } else { + map = Map::CopyInitialMap(constructor_initial_map); + } + map->set_new_target_is_base(false); + Handle<Object> prototype(new_target->instance_prototype(), isolate); + JSFunction::SetInitialMap(new_target, map, prototype); + DCHECK(new_target->instance_prototype()->IsJSReceiver()); + map->SetConstructor(*constructor); + map->set_construction_counter(Map::kNoSlackTracking); + map->StartInobjectSlackTracking(); + return true; +} + +} // namespace // static MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate, @@ -12986,55 +13038,16 @@ MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate, Handle<Map> constructor_initial_map(constructor->initial_map(), isolate); if (*new_target == *constructor) return constructor_initial_map; + Handle<Map> result_map; // Fast case, new.target is a subclass of constructor. The map is cacheable // (and may already have been cached). new.target.prototype is guaranteed to // be a JSReceiver. if (new_target->IsJSFunction()) { Handle<JSFunction> function = Handle<JSFunction>::cast(new_target); - - // Check that |function|'s initial map still in sync with the |constructor|, - // otherwise we must create a new initial map for |function|. - if (function->has_initial_map() && - function->initial_map()->GetConstructor() == *constructor) { + if (FastInitializeDerivedMap(isolate, function, constructor, + constructor_initial_map)) { return handle(function->initial_map(), isolate); } - - // Create a new map with the size and number of in-object properties - // suggested by |function|. - - // Link initial map and constructor function if the new.target is actually a - // subclass constructor. - if (IsDerivedConstructor(function->shared()->kind())) { - Handle<Object> prototype(function->instance_prototype(), isolate); - InstanceType instance_type = constructor_initial_map->instance_type(); - DCHECK(CanSubclassHaveInobjectProperties(instance_type)); - int embedder_fields = - JSObject::GetEmbedderFieldCount(*constructor_initial_map); - int pre_allocated = constructor_initial_map->GetInObjectProperties() - - constructor_initial_map->UnusedPropertyFields(); - int instance_size; - int in_object_properties; - bool success = CalculateInstanceSizeForDerivedClass( - function, instance_type, embedder_fields, &instance_size, - &in_object_properties); - - int unused_property_fields = in_object_properties - pre_allocated; - - Handle<Map> map; - if (success) { - map = Map::CopyInitialMap(constructor_initial_map, instance_size, - in_object_properties, unused_property_fields); - } else { - map = Map::CopyInitialMap(constructor_initial_map); - } - map->set_new_target_is_base(false); - - JSFunction::SetInitialMap(function, map, prototype); - map->SetConstructor(*constructor); - map->set_construction_counter(Map::kNoSlackTracking); - map->StartInobjectSlackTracking(); - return map; - } } // Slow path, new.target is either a proxy or can't cache the map. @@ -13076,7 +13089,7 @@ MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate, Handle<Map> map = Map::CopyInitialMap(constructor_initial_map); map->set_new_target_is_base(false); - DCHECK(prototype->IsJSReceiver()); + CHECK(prototype->IsJSReceiver()); if (map->prototype() != *prototype) Map::SetPrototype(map, prototype); map->SetConstructor(*constructor); return map; @@ -13183,7 +13196,8 @@ Handle<String> JSFunction::ToString(Handle<JSFunction> function) { } if (FLAG_harmony_function_tostring) { - return Handle<String>::cast(shared_info->GetSourceCodeHarmony()); + return Handle<String>::cast( + SharedFunctionInfo::GetSourceCodeHarmony(shared_info)); } IncrementalStringBuilder builder(isolate); @@ -13214,7 +13228,22 @@ Handle<String> JSFunction::ToString(Handle<JSFunction> function) { builder.AppendString(handle(shared_info->name(), isolate)); } } - builder.AppendString(Handle<String>::cast(shared_info->GetSourceCode())); + if (shared_info->is_wrapped()) { + builder.AppendCharacter('('); + Handle<FixedArray> args( + Script::cast(shared_info->script())->wrapped_arguments()); + int argc = args->length(); + for (int i = 0; i < argc; i++) { + if (i > 0) builder.AppendCString(", "); + builder.AppendString(Handle<String>(String::cast(args->get(i)))); + } + builder.AppendCString(") {\n"); + } + builder.AppendString( + Handle<String>::cast(SharedFunctionInfo::GetSourceCode(shared_info))); + if (shared_info->is_wrapped()) { + builder.AppendCString("\n}"); + } return builder.Finish().ToHandleChecked(); } @@ -13245,10 +13274,10 @@ int Script::GetEvalPosition() { // Due to laziness, the position may not have been translated from code // offset yet, which would be encoded as negative integer. In that case, // translate and set the position. - if (eval_from_shared()->IsUndefined(GetIsolate())) { + if (!has_eval_from_shared()) { position = 0; } else { - SharedFunctionInfo* shared = SharedFunctionInfo::cast(eval_from_shared()); + SharedFunctionInfo* shared = eval_from_shared(); position = shared->abstract_code()->SourcePosition(-position); } DCHECK_GE(position, 0); @@ -13286,6 +13315,15 @@ bool Script::GetPositionInfo(Handle<Script> script, int position, bool Script::IsUserJavaScript() { return type() == Script::TYPE_NORMAL; } +bool Script::ContainsAsmModule() { + DisallowHeapAllocation no_gc; + SharedFunctionInfo::ScriptIterator iter(Handle<Script>(this)); + while (SharedFunctionInfo* info = iter.Next()) { + if (info->HasAsmWasmData()) return true; + } + return false; +} + namespace { bool GetPositionInfoSlow(const Script* script, int position, Script::PositionInfo* info) { @@ -13324,8 +13362,8 @@ bool Script::GetPositionInfo(int position, PositionInfo* info, Handle<WasmCompiledModule> compiled_module( WasmCompiledModule::cast(wasm_compiled_module())); DCHECK_LE(0, position); - return compiled_module->GetPositionInfo(static_cast<uint32_t>(position), - info); + return compiled_module->shared()->GetPositionInfo( + static_cast<uint32_t>(position), info); } if (line_ends()->IsUndefined(GetIsolate())) { @@ -13456,8 +13494,12 @@ Handle<JSObject> Script::GetWrapper(Handle<Script> script) { MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo( Isolate* isolate, const FunctionLiteral* fun) { - DCHECK_NE(fun->function_literal_id(), FunctionLiteral::kIdTypeInvalid); - DCHECK_LT(fun->function_literal_id(), shared_function_infos()->length()); + CHECK_NE(fun->function_literal_id(), FunctionLiteral::kIdTypeInvalid); + // If this check fails, the problem is most probably the function id + // renumbering done by AstFunctionLiteralIdReindexer; in particular, that + // AstTraversalVisitor doesn't recurse properly in the construct which + // triggers the mismatch. + CHECK_LT(fun->function_literal_id(), shared_function_infos()->length()); Object* shared = shared_function_infos()->get(fun->function_literal_id()); if (shared->IsUndefined(isolate) || WeakCell::cast(shared)->cleared()) { return MaybeHandle<SharedFunctionInfo>(); @@ -13628,14 +13670,14 @@ String* SharedFunctionInfo::DebugName() { return name(); } -bool SharedFunctionInfo::HasNoSideEffect() { - if (!computed_has_no_side_effect()) { - DisallowHeapAllocation not_handlified; - Handle<SharedFunctionInfo> info(this); - set_has_no_side_effect(DebugEvaluate::FunctionHasNoSideEffect(info)); - set_computed_has_no_side_effect(true); +// static +bool SharedFunctionInfo::HasNoSideEffect(Handle<SharedFunctionInfo> info) { + if (!info->computed_has_no_side_effect()) { + bool has_no_side_effect = DebugEvaluate::FunctionHasNoSideEffect(info); + info->set_has_no_side_effect(has_no_side_effect); + info->set_computed_has_no_side_effect(true); } - return has_no_side_effect(); + return info->has_no_side_effect(); } // The filter is a pattern that matches function names in this way: @@ -13680,22 +13722,44 @@ bool SharedFunctionInfo::HasSourceCode() const { !reinterpret_cast<Script*>(script())->source()->IsUndefined(isolate); } - -Handle<Object> SharedFunctionInfo::GetSourceCode() { - if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value(); - Handle<String> source(String::cast(Script::cast(script())->source())); - return GetIsolate()->factory()->NewSubString( - source, start_position(), end_position()); +// static +Handle<Object> SharedFunctionInfo::GetSourceCode( + Handle<SharedFunctionInfo> shared) { + Isolate* isolate = shared->GetIsolate(); + if (!shared->HasSourceCode()) return isolate->factory()->undefined_value(); + Handle<String> source(String::cast(Script::cast(shared->script())->source())); + return isolate->factory()->NewSubString(source, shared->start_position(), + shared->end_position()); } -Handle<Object> SharedFunctionInfo::GetSourceCodeHarmony() { - Isolate* isolate = GetIsolate(); - if (!HasSourceCode()) return isolate->factory()->undefined_value(); - Handle<String> script_source(String::cast(Script::cast(script())->source())); - int start_pos = function_token_position(); - if (start_pos == kNoSourcePosition) start_pos = start_position(); - return isolate->factory()->NewSubString(script_source, start_pos, - end_position()); +// static +Handle<Object> SharedFunctionInfo::GetSourceCodeHarmony( + Handle<SharedFunctionInfo> shared) { + Isolate* isolate = shared->GetIsolate(); + if (!shared->HasSourceCode()) return isolate->factory()->undefined_value(); + Handle<String> script_source( + String::cast(Script::cast(shared->script())->source())); + int start_pos = shared->function_token_position(); + if (start_pos == kNoSourcePosition) start_pos = shared->start_position(); + Handle<String> source = isolate->factory()->NewSubString( + script_source, start_pos, shared->end_position()); + if (!shared->is_wrapped()) return source; + + DCHECK(!shared->name_should_print_as_anonymous()); + IncrementalStringBuilder builder(isolate); + builder.AppendCString("function "); + builder.AppendString(Handle<String>(shared->name(), isolate)); + builder.AppendCString("("); + Handle<FixedArray> args(Script::cast(shared->script())->wrapped_arguments()); + int argc = args->length(); + for (int i = 0; i < argc; i++) { + if (i > 0) builder.AppendCString(", "); + builder.AppendString(Handle<String>(String::cast(args->get(i)))); + } + builder.AppendCString(") {\n"); + builder.AppendString(source); + builder.AppendCString("\n}"); + return builder.Finish().ToHandleChecked(); } bool SharedFunctionInfo::IsInlineable() { @@ -13720,15 +13784,17 @@ void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type, int* instance_size, int* in_object_properties) { int header_size = JSObject::GetHeaderSize(instance_type, has_prototype_slot); - DCHECK_LE(requested_embedder_fields, - (JSObject::kMaxInstanceSize - header_size) >> kPointerSizeLog2); + int max_nof_fields = + (JSObject::kMaxInstanceSize - header_size) >> kPointerSizeLog2; + CHECK_LE(max_nof_fields, JSObject::kMaxInObjectProperties); + *in_object_properties = Min(requested_in_object_properties, max_nof_fields); + CHECK_LE(requested_embedder_fields, max_nof_fields - *in_object_properties); *instance_size = - Min(header_size + - ((requested_embedder_fields + requested_in_object_properties) - << kPointerSizeLog2), - JSObject::kMaxInstanceSize); - *in_object_properties = ((*instance_size - header_size) >> kPointerSizeLog2) - - requested_embedder_fields; + header_size + + ((requested_embedder_fields + *in_object_properties) << kPointerSizeLog2); + CHECK_EQ(*in_object_properties, + ((*instance_size - header_size) >> kPointerSizeLog2) - + requested_embedder_fields); } // static @@ -13738,7 +13804,6 @@ bool JSFunction::CalculateInstanceSizeForDerivedClass( int* in_object_properties) { Isolate* isolate = function->GetIsolate(); int expected_nof_properties = 0; - bool result = true; for (PrototypeIterator iter(isolate, function, kStartAtReceiver); !iter.IsAtEnd(); iter.Advance()) { Handle<JSReceiver> current = @@ -13751,21 +13816,24 @@ bool JSFunction::CalculateInstanceSizeForDerivedClass( if (shared->is_compiled() || Compiler::Compile(func, Compiler::CLEAR_EXCEPTION)) { DCHECK(shared->is_compiled()); - expected_nof_properties += shared->expected_nof_properties(); + int count = shared->expected_nof_properties(); + // Check that the estimate is sane. + if (expected_nof_properties <= JSObject::kMaxInObjectProperties - count) { + expected_nof_properties += count; + } else { + expected_nof_properties = JSObject::kMaxInObjectProperties; + } } else if (!shared->is_compiled()) { // In case there was a compilation error for the constructor we will // throw an error during instantiation. Hence we directly return 0; - result = false; - break; - } - if (!IsDerivedConstructor(shared->kind())) { - break; + return false; } + if (!IsDerivedConstructor(shared->kind())) break; } CalculateInstanceSizeHelper(instance_type, true, requested_embedder_fields, expected_nof_properties, instance_size, in_object_properties); - return result; + return true; } @@ -13804,7 +13872,7 @@ std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) { void SharedFunctionInfo::DisableOptimization(BailoutReason reason) { - DCHECK_NE(reason, kNoReason); + DCHECK_NE(reason, BailoutReason::kNoReason); set_compiler_hints( DisabledOptimizationReasonBits::update(compiler_hints(), reason)); @@ -13833,6 +13901,7 @@ void SharedFunctionInfo::InitFromFunctionLiteral( shared_info->set_inferred_name(*lit->inferred_name()); shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); shared_info->set_language_mode(lit->language_mode()); + shared_info->set_is_wrapped(lit->is_wrapped()); // shared_info->set_kind(lit->kind()); // FunctionKind must have already been set. DCHECK(lit->kind() == shared_info->kind()); @@ -13941,7 +14010,7 @@ void Code::InvalidateEmbeddedObjects() { void Code::Relocate(intptr_t delta) { - if (trap_handler::UseTrapHandler() && is_wasm_code()) { + if (trap_handler::IsTrapHandlerEnabled() && is_wasm_code()) { const int index = trap_handler_index()->value(); if (index >= 0) { trap_handler::UpdateHandlerDataCodePointer(index, instruction_start()); @@ -14101,11 +14170,11 @@ void JSFunction::ClearTypeFeedbackInfo() { } } -void Code::PrintDeoptLocation(FILE* out, Address pc) { +void Code::PrintDeoptLocation(FILE* out, const char* str, Address pc) { Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc); class SourcePosition pos = info.position; - if (info.deopt_reason != DeoptimizeReason::kNoReason || pos.IsKnown()) { - PrintF(out, " ;;; deoptimize at "); + if (info.deopt_reason != DeoptimizeReason::kUnknown || pos.IsKnown()) { + PrintF(out, "%s", str); OFStream outstr(out); pos.Print(outstr, this); PrintF(out, ", %s\n", DeoptimizeReasonToString(info.deopt_reason)); @@ -14291,9 +14360,11 @@ void DeoptimizationData::DeoptimizationDataPrint(std::ostream& os) { // NOLINT DCHECK(Translation::BEGIN == opcode); int frame_count = iterator.Next(); int jsframe_count = iterator.Next(); + int update_feedback_count = iterator.Next(); os << " " << Translation::StringFor(opcode) << " {frame count=" << frame_count - << ", js frame count=" << jsframe_count << "}\n"; + << ", js frame count=" << jsframe_count + << ", update_feedback_count=" << update_feedback_count << "}\n"; while (iterator.HasNext() && Translation::BEGIN != @@ -14450,6 +14521,14 @@ void DeoptimizationData::DeoptimizationDataPrint(std::ostream& os) { // NOLINT os << "{length=" << args_length << "}"; break; } + + case Translation::UPDATE_FEEDBACK: { + int literal_index = iterator.Next(); + FeedbackSlot slot(iterator.Next()); + os << "{feedback={vector_index=" << literal_index << ", slot=" << slot + << "}}"; + break; + } } os << "\n"; } @@ -14485,8 +14564,7 @@ void HandlerTable::HandlerTableReturnPrint(std::ostream& os) { } } - -void Code::Disassemble(const char* name, std::ostream& os) { // NOLINT +void Code::Disassemble(const char* name, std::ostream& os, void* current_pc) { os << "kind = " << Kind2String(kind()) << "\n"; if (is_stub()) { const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this)); @@ -14514,21 +14592,22 @@ void Code::Disassemble(const char* name, std::ostream& os) { // NOLINT os << "compiler = " << (is_turbofanned() ? "turbofan" : "unknown") << "\n"; os << "address = " << static_cast<const void*>(this) << "\n"; - os << "Instructions (size = " << instruction_size() << ")\n"; + os << "Body (size = " << instruction_size() << ")\n"; { Isolate* isolate = GetIsolate(); int size = instruction_size(); int safepoint_offset = - is_turbofanned() ? static_cast<int>(safepoint_table_offset()) : size; + has_safepoint_info() ? safepoint_table_offset() : size; int constant_pool_offset = FLAG_enable_embedded_constant_pool ? this->constant_pool_offset() : size; // Stop before reaching any embedded tables int code_size = Min(safepoint_offset, constant_pool_offset); + os << "Instructions (size = " << code_size << ")\n"; byte* begin = instruction_start(); byte* end = begin + code_size; - Disassembler::Decode(isolate, &os, begin, end, this); + Disassembler::Decode(isolate, &os, begin, end, this, current_pc); if (constant_pool_offset < size) { int constant_pool_size = safepoint_offset - constant_pool_offset; @@ -14562,7 +14641,7 @@ void Code::Disassemble(const char* name, std::ostream& os) { // NOLINT } os << "\n"; - if (is_turbofanned()) { + if (has_safepoint_info()) { SafepointTable table(this); os << "Safepoints (size = " << table.size() << ")\n"; for (unsigned i = 0; i < table.length(); i++) { @@ -15057,7 +15136,7 @@ Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value, return Nothing<bool>(); } // 5. Let target be the value of the [[ProxyTarget]] internal slot. - Handle<JSReceiver> target(proxy->target(), isolate); + Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); // 6. Let trap be ? GetMethod(handler, "getPrototypeOf"). Handle<Object> trap; ASSIGN_RETURN_ON_EXCEPTION_VALUE( @@ -15267,13 +15346,10 @@ static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity, bool JSObject::WouldConvertToSlowElements(uint32_t index) { - if (HasFastElements()) { - Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements())); - uint32_t capacity = static_cast<uint32_t>(backing_store->length()); - uint32_t new_capacity; - return ShouldConvertToSlowElements(this, capacity, index, &new_capacity); - } - return false; + if (!HasFastElements()) return false; + uint32_t capacity = static_cast<uint32_t>(elements()->length()); + uint32_t new_capacity; + return ShouldConvertToSlowElements(this, capacity, index, &new_capacity); } @@ -16655,26 +16731,18 @@ MaybeHandle<JSTypedArray> JSTypedArray::SpeciesCreate( // 2. Let defaultConstructor be the intrinsic object listed in column one of // Table 51 for exemplar.[[TypedArrayName]]. - Handle<JSFunction> default_ctor = isolate->uint8_array_fun(); - switch (exemplar->type()) { -#define TYPED_ARRAY_CTOR(Type, type, TYPE, ctype, size) \ - case kExternal##Type##Array: { \ - default_ctor = isolate->type##_array_fun(); \ - break; \ - } - - TYPED_ARRAYS(TYPED_ARRAY_CTOR) -#undef TYPED_ARRAY_CTOR - default: - UNREACHABLE(); - } + Handle<JSFunction> default_ctor = + JSTypedArray::DefaultConstructor(isolate, exemplar); // 3. Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor). - Handle<Object> ctor; - ASSIGN_RETURN_ON_EXCEPTION( - isolate, ctor, - Object::SpeciesConstructor(isolate, exemplar, default_ctor), - JSTypedArray); + Handle<Object> ctor = default_ctor; + if (!exemplar->HasJSTypedArrayPrototype(isolate) || + !isolate->IsArraySpeciesLookupChainIntact()) { + ASSIGN_RETURN_ON_EXCEPTION( + isolate, ctor, + Object::SpeciesConstructor(isolate, exemplar, default_ctor), + JSTypedArray); + } // 4. Return ? TypedArrayCreate(constructor, argumentList). return Create(isolate, ctor, argc, argv, method_name); @@ -16682,6 +16750,10 @@ MaybeHandle<JSTypedArray> JSTypedArray::SpeciesCreate( void JSGlobalObject::InvalidatePropertyCell(Handle<JSGlobalObject> global, Handle<Name> name) { + // Regardless of whether the property is there or not invalidate + // Load/StoreGlobalICs that load/store through global object's prototype. + JSObject::InvalidatePrototypeValidityCell(*global); + DCHECK(!global->HasFastProperties()); auto dictionary = handle(global->global_dictionary()); int entry = dictionary->FindEntry(name); @@ -17703,6 +17775,8 @@ Handle<FixedArray> BaseNameDictionary<Derived, Shape>::IterationIndices( array->set(array_size++, Smi::FromInt(i)); } + DCHECK_EQ(array_size, length); + EnumIndexComparator<Derived> cmp(raw_dictionary); // Use AtomicElement wrapper to ensure that std::sort uses atomic load and // store operations that are safe for concurrent marking. @@ -18924,6 +18998,13 @@ void JSArrayBuffer::FreeBackingStore() { // static void JSArrayBuffer::FreeBackingStore(Isolate* isolate, Allocation allocation) { + if (allocation.mode == ArrayBuffer::Allocator::AllocationMode::kReservation) { + // TODO(eholk): check with WasmAllocationTracker to make sure this is + // actually a buffer we are tracking. + isolate->wasm_engine()->allocation_tracker()->ReleaseAddressSpace( + allocation.length); + } + isolate->array_buffer_allocator()->Free(allocation.allocation_base, allocation.length, allocation.mode); } @@ -18959,7 +19040,7 @@ void JSArrayBuffer::Setup(Handle<JSArrayBuffer> array_buffer, Isolate* isolate, // already been promoted. array_buffer->set_backing_store(data); - array_buffer->set_allocation_base(data); + array_buffer->set_allocation_base(allocation_base); array_buffer->set_allocation_length(allocation_length); if (data && !is_external) { @@ -19179,6 +19260,14 @@ Handle<PropertyCell> PropertyCell::PrepareForValue( details = details.set_cell_type(new_type); cell->set_property_details(details); + if (new_type == PropertyCellType::kConstant || + new_type == PropertyCellType::kConstantType) { + // Store the value now to ensure that the cell contains the constant or + // type information. Otherwise subsequent store operation will turn + // the cell to mutable. + cell->set_value(*value); + } + // Deopt when transitioning from a constant type. if (!invalidate && (old_type != new_type || original_details.IsReadOnly() != details.IsReadOnly())) { |