TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) { auto context = Parameter<Context>(Descriptor::kContext); auto target = Parameter<JSFunction>(Descriptor::kTarget); auto new_target = Parameter<JSReceiver>(Descriptor::kNewTarget);
Label call_runtime(this);
TNode<JSObject> result = FastNewObject(context, target, new_target, &call_runtime); Return(result);
TNode<JSObject> ConstructorBuiltinsAssembler::FastNewObject( TNode<Context> context, TNode<JSFunction> target, TNode<JSReceiver> new_target, Label* call_runtime){ // Verify that the new target is a JSFunction. Label end(this); TNode<JSFunction> new_target_func = HeapObjectToJSFunctionWithPrototypeSlot(new_target, call_runtime); // Fast path.
// Load the initial map and verify that it's in fact a map. TNode<Object> initial_map_or_proto = LoadJSFunctionPrototypeOrInitialMap(new_target_func); GotoIf(TaggedIsSmi(initial_map_or_proto), call_runtime); GotoIf(DoesntHaveInstanceType(CAST(initial_map_or_proto), MAP_TYPE), call_runtime); TNode<Map> initial_map = CAST(initial_map_or_proto);
// Fall back to runtime if the target differs from the new target's // initial map constructor. TNode<Object> new_target_constructor = LoadObjectField( initial_map, Map::kConstructorOrBackPointerOrNativeContextOffset); GotoIf(TaggedNotEqual(target, new_target_constructor), call_runtime);
// Fall back to runtime if the target differs from the new target's // initial map constructor. TNode<Object> new_target_constructor = LoadObjectField( initial_map, Map::kConstructorOrBackPointerOrNativeContextOffset); GotoIf(TaggedNotEqual(target, new_target_constructor), call_runtime);
// static MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor, Handle<JSReceiver> new_target, Handle<AllocationSite> site){ // If called through new, new.target can be: // - a subclass of constructor, // - a proxy wrapper around constructor, or // - the constructor itself. // If called through Reflect.construct, it's guaranteed to be a constructor. Isolate* const isolate = constructor->GetIsolate(); DCHECK(constructor->IsConstructor()); DCHECK(new_target->IsConstructor()); DCHECK(!constructor->has_initial_map() || !InstanceTypeChecker::IsJSFunction( constructor->initial_map().instance_type()));
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); if (FastInitializeDerivedMap(isolate, function, constructor, constructor_initial_map)) { returnhandle(function->initial_map(), isolate); } }
// Slow path, new.target is either a proxy or can't cache the map. // new.target.prototype is not guaranteed to be a JSReceiver, and may need to // fall back to the intrinsicDefaultProto. Handle<Object> prototype; if (new_target->IsJSFunction()) { Handle<JSFunction> function = Handle<JSFunction>::cast(new_target); if (function->has_prototype_slot()) { // Make sure the new.target.prototype is cached. EnsureHasInitialMap(function); prototype = handle(function->prototype(), isolate); } else { // No prototype property, use the intrinsict default proto further down. prototype = isolate->factory()->undefined_value(); } } else { Handle<String> prototype_string = isolate->factory()->prototype_string(); ASSIGN_RETURN_ON_EXCEPTION( isolate, prototype, JSReceiver::GetProperty(isolate, new_target, prototype_string), Map); // The above prototype lookup might change the constructor and its // prototype, hence we have to reload the initial map. EnsureHasInitialMap(constructor); constructor_initial_map = handle(constructor->initial_map(), isolate); }
// If prototype is not a JSReceiver, fetch the intrinsicDefaultProto from the // correct realm. Rather than directly fetching the .prototype, we fetch the // constructor that points to the .prototype. This relies on // constructor.prototype being FROZEN for those constructors. if (!prototype->IsJSReceiver()) { Handle<Context> context; ASSIGN_RETURN_ON_EXCEPTION(isolate, context, JSReceiver::GetFunctionRealm(new_target), Map); DCHECK(context->IsNativeContext()); Handle<Object> maybe_index = JSReceiver::GetDataProperty( isolate, constructor, isolate->factory()->native_context_index_symbol()); int index = maybe_index->IsSmi() ? Smi::ToInt(*maybe_index) : Context::OBJECT_FUNCTION_INDEX; Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)), isolate); prototype = handle(realm_constructor->prototype(), isolate); }
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); if (FastInitializeDerivedMap(isolate, function, constructor, constructor_initial_map)) { returnhandle(function->initial_map(), isolate); } }
boolFastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target, Handle<JSFunction> constructor, Handle<Map> constructor_initial_map){ // Use the default intrinsic prototype instead. if (!new_target->has_prototype_slot()) returnfalse; // 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()); returntrue; } 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())) returnfalse;
int instance_size; int in_object_properties; int embedder_fields = JSObject::GetEmbedderFieldCount(*constructor_initial_map); // Constructor expects certain number of in-object properties to be in the // object. However, CalculateExpectedNofProperties() may return smaller value // if 1) the constructor is not in the prototype chain of new_target, or // 2) the prototype chain is modified during iteration, or 3) compilation // failure occur during prototype chain iteration. // So we take the maximum of two values. int expected_nof_properties = std::max( static_cast<int>(constructor->shared().expected_nof_properties()), JSFunction::CalculateExpectedNofProperties(isolate, new_target)); JSFunction::CalculateInstanceSizeHelper( instance_type, constructor_initial_map->has_prototype_slot(), embedder_fields, expected_nof_properties, &instance_size, &in_object_properties);
boolFastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target, Handle<JSFunction> constructor, Handle<Map> constructor_initial_map){ // Use the default intrinsic prototype instead. if (!new_target->has_prototype_slot()) returnfalse; // 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()); returntrue; }
// Slow path, new.target is either a proxy or can't cache the map. // new.target.prototype is not guaranteed to be a JSReceiver, and may need to // fall back to the intrinsicDefaultProto. Handle<Object> prototype; if (new_target->IsJSFunction()) { Handle<JSFunction> function = Handle<JSFunction>::cast(new_target); if (function->has_prototype_slot()) { // Make sure the new.target.prototype is cached. EnsureHasInitialMap(function); prototype = handle(function->prototype(), isolate); } else { // No prototype property, use the intrinsict default proto further down. prototype = isolate->factory()->undefined_value(); } } else { Handle<String> prototype_string = isolate->factory()->prototype_string(); ASSIGN_RETURN_ON_EXCEPTION( isolate, prototype, JSReceiver::GetProperty(isolate, new_target, prototype_string), Map); // The above prototype lookup might change the constructor and its // prototype, hence we have to reload the initial map. EnsureHasInitialMap(constructor); constructor_initial_map = handle(constructor->initial_map(), isolate); }
// Keep walking up the class tree. current = current_function.map(broker()).prototype(broker()); } StoreRegister(register_pair.first, GetBooleanConstant(false)); StoreRegister(register_pair.second, GetConstant(current)); return; }
➜ x64.release git:(11.5.150.16) ldd --version ldd (Ubuntu GLIBC 2.35-0ubuntu3.10) 2.35 Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the sourcefor copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Roland McGrath and Ulrich Drepper. ➜ x64.release git:(11.5.150.16) lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.4 LTS Release: 22.04 Codename: jammy
var buf = newArrayBuffer(8); var f32 = newFloat32Array(buf); var f64 = newFloat64Array(buf); var u8 = newUint8Array(buf); var u16 = newUint16Array(buf); var u32 = newUint32Array(buf); var u64 = newBigUint64Array(buf);