diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-06-06 10:28:14 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-06-07 10:33:31 +0200 |
commit | 3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09 (patch) | |
tree | 9dee56e142638b34f1eccbd0ad88c3bce5377c29 /deps/v8/src/compiler/js-native-context-specialization.cc | |
parent | 91a1bbe3055a660194ca4d403795aa0c03e9d056 (diff) | |
download | node-new-3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09.tar.gz |
deps: update V8 to 5.9.211.32
PR-URL: https://github.com/nodejs/node/pull/13263
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Diffstat (limited to 'deps/v8/src/compiler/js-native-context-specialization.cc')
-rw-r--r-- | deps/v8/src/compiler/js-native-context-specialization.cc | 287 |
1 files changed, 150 insertions, 137 deletions
diff --git a/deps/v8/src/compiler/js-native-context-specialization.cc b/deps/v8/src/compiler/js-native-context-specialization.cc index c32ee269a0..66013b85ca 100644 --- a/deps/v8/src/compiler/js-native-context-specialization.cc +++ b/deps/v8/src/compiler/js-native-context-specialization.cc @@ -138,9 +138,6 @@ Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor( DCHECK_EQ(IrOpcode::kJSGetSuperConstructor, node->opcode()); Node* constructor = NodeProperties::GetValueInput(node, 0); - // If deoptimization is disabled, we cannot optimize. - if (!(flags() & kDeoptimizationEnabled)) return NoChange(); - // Check if the input is a known JSFunction. HeapObjectMatcher m(constructor); if (!m.HasValue()) return NoChange(); @@ -176,9 +173,6 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) { Node* effect = NodeProperties::GetEffectInput(node); Node* control = NodeProperties::GetControlInput(node); - // If deoptimization is disabled, we cannot optimize. - if (!(flags() & kDeoptimizationEnabled)) return NoChange(); - // Check if the right hand side is a known {receiver}. HeapObjectMatcher m(constructor); if (!m.HasValue() || !m.Value()->IsJSObject()) return NoChange(); @@ -217,21 +211,37 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) { Reduction const reduction = ReduceJSOrdinaryHasInstance(node); return reduction.Changed() ? reduction : Changed(node); } - } else if (access_info.IsDataConstant()) { - DCHECK(access_info.constant()->IsCallable()); - + } else if (access_info.IsDataConstant() || + access_info.IsDataConstantField()) { // Determine actual holder and perform prototype chain checks. Handle<JSObject> holder; if (access_info.holder().ToHandle(&holder)) { AssumePrototypesStable(access_info.receiver_maps(), holder); + } else { + holder = receiver; + } + + Handle<Object> constant; + if (access_info.IsDataConstant()) { + DCHECK(!FLAG_track_constant_fields); + constant = access_info.constant(); + } else { + DCHECK(FLAG_track_constant_fields); + DCHECK(access_info.IsDataConstantField()); + // The value must be callable therefore tagged. + DCHECK(CanBeTaggedPointer(access_info.field_representation())); + FieldIndex field_index = access_info.field_index(); + constant = JSObject::FastPropertyAt(holder, Representation::Tagged(), + field_index); } + DCHECK(constant->IsCallable()); // Monomorphic property access. effect = BuildCheckMaps(constructor, effect, control, access_info.receiver_maps()); // Call the @@hasInstance handler. - Node* target = jsgraph()->Constant(access_info.constant()); + Node* target = jsgraph()->Constant(constant); node->InsertInput(graph()->zone(), 0, target); node->ReplaceInput(1, constructor); node->ReplaceInput(2, object); @@ -513,9 +523,6 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) { return Replace(value); } - // Not much we can do if deoptimization support is disabled. - if (!(flags() & kDeoptimizationEnabled)) return NoChange(); - // Lookup the {name} on the global object instead. return ReduceGlobalAccess(node, nullptr, nullptr, name, AccessMode::kLoad); } @@ -539,9 +546,6 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) { return Replace(value); } - // Not much we can do if deoptimization support is disabled. - if (!(flags() & kDeoptimizationEnabled)) return NoChange(); - // Lookup the {name} on the global object instead. return ReduceGlobalAccess(node, nullptr, value, name, AccessMode::kStore); } @@ -549,7 +553,7 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) { Reduction JSNativeContextSpecialization::ReduceNamedAccess( Node* node, Node* value, MapHandleList const& receiver_maps, Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, - Handle<FeedbackVector> vector, FeedbackSlot slot, Node* index) { + Node* index) { DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || node->opcode() == IrOpcode::kJSStoreNamed || node->opcode() == IrOpcode::kJSLoadProperty || @@ -561,9 +565,6 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( Node* effect = NodeProperties::GetEffectInput(node); Node* control = NodeProperties::GetControlInput(node); - // Not much we can do if deoptimization support is disabled. - if (!(flags() & kDeoptimizationEnabled)) return NoChange(); - // Check if we have an access o.x or o.x=v where o is the current // native contexts' global proxy, and turn that into a direct access // to the current native contexts' global object instead. @@ -598,13 +599,6 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( if (is_exceptional || !(flags() & kAccessorInliningEnabled)) { return NoChange(); } - } else if (access_info.IsGeneric()) { - // We do not handle generic calls in try blocks. - if (is_exceptional) return NoChange(); - // We only handle the generic store IC case. - if (!vector->IsStoreIC(slot)) { - return NoChange(); - } } } @@ -643,7 +637,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( // Generate the actual property access. ValueEffectControl continuation = BuildPropertyAccess( receiver, value, context, frame_state, effect, control, name, - access_info, access_mode, language_mode, vector, slot); + access_info, access_mode, language_mode); value = continuation.value(); effect = continuation.effect(); control = continuation.control(); @@ -746,10 +740,9 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( } // Generate the actual property access. - ValueEffectControl continuation = - BuildPropertyAccess(this_receiver, this_value, context, frame_state, - this_effect, this_control, name, access_info, - access_mode, language_mode, vector, slot); + ValueEffectControl continuation = BuildPropertyAccess( + this_receiver, this_value, context, frame_state, this_effect, + this_control, name, access_info, access_mode, language_mode); values.push_back(continuation.value()); effects.push_back(continuation.effect()); controls.push_back(continuation.control()); @@ -790,19 +783,16 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus( Node* const receiver = NodeProperties::GetValueInput(node, 0); Node* const effect = NodeProperties::GetEffectInput(node); - if (flags() & kDeoptimizationEnabled) { - // Check if we are accessing the current native contexts' global proxy. - HeapObjectMatcher m(receiver); - if (m.HasValue() && m.Value().is_identical_to(global_proxy())) { - // Optimize accesses to the current native contexts' global proxy. - return ReduceGlobalAccess(node, nullptr, value, name, access_mode); - } + // Check if we are accessing the current native contexts' global proxy. + HeapObjectMatcher m(receiver); + if (m.HasValue() && m.Value().is_identical_to(global_proxy())) { + // Optimize accesses to the current native contexts' global proxy. + return ReduceGlobalAccess(node, nullptr, value, name, access_mode); } // Check if the {nexus} reports type feedback for the IC. if (nexus.IsUninitialized()) { - if ((flags() & kDeoptimizationEnabled) && - (flags() & kBailoutOnUninitialized)) { + if (flags() & kBailoutOnUninitialized) { return ReduceSoftDeoptimize( node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); @@ -815,8 +805,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus( if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { return NoChange(); } else if (receiver_maps.length() == 0) { - if ((flags() & kDeoptimizationEnabled) && - (flags() & kBailoutOnUninitialized)) { + if (flags() & kBailoutOnUninitialized) { return ReduceSoftDeoptimize( node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); @@ -826,7 +815,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus( // Try to lower the named access based on the {receiver_maps}. return ReduceNamedAccess(node, value, receiver_maps, name, access_mode, - language_mode, nexus.vector_handle(), nexus.slot()); + language_mode); } Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) { @@ -847,14 +836,12 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) { // {function} in order to be notified about changes to the // "prototype" of {function}, so it doesn't make sense to // continue unless deoptimization is enabled. - if (flags() & kDeoptimizationEnabled) { - Handle<Map> initial_map(function->initial_map(), isolate()); - dependencies()->AssumeInitialMapCantChange(initial_map); - Handle<Object> prototype(initial_map->prototype(), isolate()); - Node* value = jsgraph()->Constant(prototype); - ReplaceWithValue(node, value); - return Replace(value); - } + Handle<Map> initial_map(function->initial_map(), isolate()); + dependencies()->AssumeInitialMapCantChange(initial_map); + Handle<Object> prototype(function->prototype(), isolate()); + Node* value = jsgraph()->Constant(prototype); + ReplaceWithValue(node, value); + return Replace(value); } } else if (m.Value()->IsString() && p.name().is_identical_to(factory()->length_string())) { @@ -915,9 +902,6 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( Node* control = NodeProperties::GetControlInput(node); Node* frame_state = NodeProperties::FindFrameStateBefore(node); - // Not much we can do if deoptimization support is disabled. - if (!(flags() & kDeoptimizationEnabled)) return NoChange(); - // Check for keyed access to strings. if (HasOnlyStringMaps(receiver_maps)) { // Strings are immutable in JavaScript. @@ -1163,41 +1147,40 @@ Reduction JSNativeContextSpecialization::ReduceKeyedAccess( if (mreceiver.HasValue() && mreceiver.Value()->IsString()) { Handle<String> string = Handle<String>::cast(mreceiver.Value()); + // Strings are immutable in JavaScript. + if (access_mode == AccessMode::kStore) return NoChange(); + + // Properly deal with constant {index}. + NumberMatcher mindex(index); + if (mindex.IsInteger() && mindex.IsInRange(0.0, string->length() - 1)) { + // Constant-fold the {index} access to {string}. + Node* value = jsgraph()->HeapConstant( + factory()->LookupSingleCharacterStringFromCode( + string->Get(static_cast<int>(mindex.Value())))); + ReplaceWithValue(node, value, effect, control); + return Replace(value); + } + // We can only assume that the {index} is a valid array index if the IC // is in element access mode and not MEGAMORPHIC, otherwise there's no // guard for the bounds check below. if (nexus.ic_state() != MEGAMORPHIC && nexus.GetKeyType() == ELEMENT) { - // Strings are immutable in JavaScript. - if (access_mode == AccessMode::kStore) return NoChange(); - - // Properly deal with constant {index}. - NumberMatcher mindex(index); - if (mindex.IsInteger() && mindex.IsInRange(0.0, string->length() - 1)) { - // Constant-fold the {index} access to {string}. - Node* value = jsgraph()->HeapConstant( - factory()->LookupSingleCharacterStringFromCode( - string->Get(static_cast<int>(mindex.Value())))); - ReplaceWithValue(node, value, effect, control); - return Replace(value); - } else if (flags() & kDeoptimizationEnabled) { - // Ensure that {index} is less than {receiver} length. - Node* length = jsgraph()->Constant(string->length()); - index = effect = graph()->NewNode(simplified()->CheckBounds(), index, - length, effect, control); - - // Return the character from the {receiver} as single character string. - value = graph()->NewNode(simplified()->StringCharAt(), receiver, index, - control); - ReplaceWithValue(node, value, effect, control); - return Replace(value); - } + // Ensure that {index} is less than {receiver} length. + Node* length = jsgraph()->Constant(string->length()); + index = effect = graph()->NewNode(simplified()->CheckBounds(), index, + length, effect, control); + + // Return the character from the {receiver} as single character string. + value = graph()->NewNode(simplified()->StringCharAt(), receiver, index, + control); + ReplaceWithValue(node, value, effect, control); + return Replace(value); } } // Check if the {nexus} reports type feedback for the IC. if (nexus.IsUninitialized()) { - if ((flags() & kDeoptimizationEnabled) && - (flags() & kBailoutOnUninitialized)) { + if (flags() & kBailoutOnUninitialized) { return ReduceSoftDeoptimize( node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); @@ -1210,8 +1193,7 @@ Reduction JSNativeContextSpecialization::ReduceKeyedAccess( if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { return NoChange(); } else if (receiver_maps.length() == 0) { - if ((flags() & kDeoptimizationEnabled) && - (flags() & kBailoutOnUninitialized)) { + if (flags() & kBailoutOnUninitialized) { return ReduceSoftDeoptimize( node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); @@ -1235,17 +1217,16 @@ Reduction JSNativeContextSpecialization::ReduceKeyedAccess( } else { name = factory()->InternalizeName(name); return ReduceNamedAccess(node, value, receiver_maps, name, access_mode, - language_mode, nexus.vector_handle(), - nexus.slot()); + language_mode); } } } // Check if we have feedback for a named access. if (Name* name = nexus.FindFirstName()) { - return ReduceNamedAccess( - node, value, receiver_maps, handle(name, isolate()), access_mode, - language_mode, nexus.vector_handle(), nexus.slot(), index); + return ReduceNamedAccess(node, value, receiver_maps, + handle(name, isolate()), access_mode, + language_mode, index); } else if (nexus.GetKeyType() != ELEMENT) { // The KeyedLoad/StoreIC has seen non-element accesses, so we cannot assume // that the {index} is a valid array index, thus we just let the IC continue @@ -1319,8 +1300,7 @@ JSNativeContextSpecialization::ValueEffectControl JSNativeContextSpecialization::BuildPropertyAccess( Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect, Node* control, Handle<Name> name, PropertyAccessInfo const& access_info, - AccessMode access_mode, LanguageMode language_mode, - Handle<FeedbackVector> vector, FeedbackSlot slot) { + AccessMode access_mode, LanguageMode language_mode) { // Determine actual holder and perform prototype chain checks. Handle<JSObject> holder; if (access_info.holder().ToHandle(&holder)) { @@ -1333,6 +1313,7 @@ JSNativeContextSpecialization::BuildPropertyAccess( DCHECK_EQ(AccessMode::kLoad, access_mode); value = jsgraph()->UndefinedConstant(); } else if (access_info.IsDataConstant()) { + DCHECK(!FLAG_track_constant_fields); Node* constant_value = jsgraph()->Constant(access_info.constant()); if (access_mode == AccessMode::kStore) { Node* check = graph()->NewNode(simplified()->ReferenceEqual(), value, @@ -1365,11 +1346,10 @@ JSNativeContextSpecialization::BuildPropertyAccess( // Introduce the call to the getter function. if (access_info.constant()->IsJSFunction()) { - value = effect = graph()->NewNode( + value = effect = control = graph()->NewNode( javascript()->Call(2, 0.0f, VectorSlotPair(), ConvertReceiverMode::kNotNullOrUndefined), target, receiver, context, frame_state0, effect, control); - control = graph()->NewNode(common()->IfSuccess(), value); } else { DCHECK(access_info.constant()->IsFunctionTemplateInfo()); Handle<FunctionTemplateInfo> function_template_info( @@ -1402,11 +1382,10 @@ JSNativeContextSpecialization::BuildPropertyAccess( // Introduce the call to the setter function. if (access_info.constant()->IsJSFunction()) { - effect = graph()->NewNode( + effect = control = graph()->NewNode( javascript()->Call(3, 0.0f, VectorSlotPair(), ConvertReceiverMode::kNotNullOrUndefined), target, receiver, value, context, frame_state0, effect, control); - control = graph()->NewNode(common()->IfSuccess(), effect); } else { DCHECK(access_info.constant()->IsFunctionTemplateInfo()); Handle<FunctionTemplateInfo> function_template_info( @@ -1422,7 +1401,8 @@ JSNativeContextSpecialization::BuildPropertyAccess( break; } } - } else if (access_info.IsDataField() || access_info.IsDataConstantField()) { + } else { + DCHECK(access_info.IsDataField() || access_info.IsDataConstantField()); FieldIndex const field_index = access_info.field_index(); Type* const field_type = access_info.field_type(); MachineRepresentation const field_representation = @@ -1531,7 +1511,7 @@ JSNativeContextSpecialization::BuildPropertyAccess( common()->BeginRegion(RegionObservability::kNotObservable), effect); Node* box = effect = graph()->NewNode( - simplified()->Allocate(NOT_TENURED), + simplified()->Allocate(Type::OtherInternal(), NOT_TENURED), jsgraph()->Constant(HeapNumber::kSize), effect, control); effect = graph()->NewNode( simplified()->StoreField(AccessBuilder::ForMap()), box, @@ -1634,44 +1614,44 @@ JSNativeContextSpecialization::BuildPropertyAccess( UNREACHABLE(); break; } + // Check if we need to perform a transitioning store. Handle<Map> transition_map; if (access_info.transition_map().ToHandle(&transition_map)) { + // Check if we need to grow the properties backing store + // with this transitioning store. + Handle<Map> original_map(Map::cast(transition_map->GetBackPointer()), + isolate()); + if (original_map->unused_property_fields() == 0) { + DCHECK(!field_index.is_inobject()); + + // Reallocate the properties {storage}. + storage = effect = BuildExtendPropertiesBackingStore( + original_map, storage, effect, control); + + // Perform the actual store. + effect = graph()->NewNode(simplified()->StoreField(field_access), + storage, value, effect, control); + + // Atomically switch to the new properties below. + field_access = AccessBuilder::ForJSObjectProperties(); + value = storage; + storage = receiver; + } effect = graph()->NewNode( common()->BeginRegion(RegionObservability::kObservable), effect); effect = graph()->NewNode( simplified()->StoreField(AccessBuilder::ForMap()), receiver, jsgraph()->Constant(transition_map), effect, control); - } - effect = graph()->NewNode(simplified()->StoreField(field_access), storage, - value, effect, control); - if (access_info.HasTransitionMap()) { + effect = graph()->NewNode(simplified()->StoreField(field_access), + storage, value, effect, control); effect = graph()->NewNode(common()->FinishRegion(), jsgraph()->UndefinedConstant(), effect); + } else { + // Regular non-transitioning field store. + effect = graph()->NewNode(simplified()->StoreField(field_access), + storage, value, effect, control); } } - } else { - DCHECK(access_info.IsGeneric()); - DCHECK_EQ(AccessMode::kStore, access_mode); - DCHECK(vector->IsStoreIC(slot)); - DCHECK_EQ(vector->GetLanguageMode(slot), language_mode); - Callable callable = - CodeFactory::StoreICInOptimizedCode(isolate(), language_mode); - const CallInterfaceDescriptor& descriptor = callable.descriptor(); - CallDescriptor* desc = Linkage::GetStubCallDescriptor( - isolate(), graph()->zone(), descriptor, - descriptor.GetStackParameterCount(), CallDescriptor::kNeedsFrameState, - Operator::kNoProperties); - Node* stub_code = jsgraph()->HeapConstant(callable.code()); - Node* name_node = jsgraph()->HeapConstant(name); - Node* slot_node = jsgraph()->Constant(vector->GetIndex(slot)); - Node* vector_node = jsgraph()->HeapConstant(vector); - - Node* inputs[] = {stub_code, receiver, name_node, value, slot_node, - vector_node, context, frame_state, effect, control}; - - value = effect = control = - graph()->NewNode(common()->Call(desc), arraysize(inputs), inputs); - control = graph()->NewNode(common()->IfSuccess(), control); } return ValueEffectControl(value, effect, control); @@ -1681,10 +1661,7 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral( Node* node) { DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode()); - // If deoptimization is disabled, we cannot optimize. - if (!(flags() & kDeoptimizationEnabled)) return NoChange(); - - DataPropertyParameters const& p = DataPropertyParametersOf(node->op()); + FeedbackParameter const& p = FeedbackParameterOf(node->op()); if (!p.feedback().IsValid()) return NoChange(); @@ -1719,10 +1696,6 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral( return NoChange(); } - if (access_info.IsGeneric()) { - return NoChange(); - } - Node* receiver = NodeProperties::GetValueInput(node, 0); Node* effect = NodeProperties::GetEffectInput(node); Node* control = NodeProperties::GetControlInput(node); @@ -1746,8 +1719,7 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral( // Generate the actual property access. ValueEffectControl continuation = BuildPropertyAccess( receiver, value, context, frame_state_lazy, effect, control, cached_name, - access_info, AccessMode::kStoreInLiteral, LanguageMode::SLOPPY, - p.feedback().vector(), p.feedback().slot()); + access_info, AccessMode::kStoreInLiteral, LanguageMode::SLOPPY); value = continuation.value(); effect = continuation.effect(); control = continuation.control(); @@ -1990,10 +1962,12 @@ JSNativeContextSpecialization::BuildElementAccess( if (access_mode == AccessMode::kLoad) { // Compute the real element access type, which includes the hole in case // of holey backing stores. - if (elements_kind == FAST_HOLEY_ELEMENTS || - elements_kind == FAST_HOLEY_SMI_ELEMENTS) { + if (IsHoleyElementsKind(elements_kind)) { element_access.type = Type::Union(element_type, Type::Hole(), graph()->zone()); + } + if (elements_kind == FAST_HOLEY_ELEMENTS || + elements_kind == FAST_HOLEY_SMI_ELEMENTS) { element_access.machine_type = MachineType::AnyTagged(); } // Perform the actual backing store access. @@ -2117,10 +2091,10 @@ JSNativeContextSpecialization::InlineApiCall( inputs[6] = value; } + Node* control0; Node* effect0; - Node* value0 = effect0 = + Node* value0 = effect0 = control0 = graph()->NewNode(common()->Call(call_descriptor), index, inputs); - Node* control0 = graph()->NewNode(common()->IfSuccess(), value0); return ValueEffectControl(value0, effect0, control0); } @@ -2178,6 +2152,45 @@ Node* JSNativeContextSpecialization::BuildCheckMaps( effect, control); } +Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore( + Handle<Map> map, Node* properties, Node* effect, Node* control) { + DCHECK_EQ(0, map->unused_property_fields()); + // Compute the length of the old {properties} and the new properties. + int length = map->NextFreePropertyIndex() - map->GetInObjectProperties(); + int new_length = length + JSObject::kFieldsAdded; + // Collect the field values from the {properties}. + ZoneVector<Node*> values(zone()); + values.reserve(new_length); + for (int i = 0; i < length; ++i) { + Node* value = effect = graph()->NewNode( + simplified()->LoadField(AccessBuilder::ForFixedArraySlot(i)), + properties, effect, control); + values.push_back(value); + } + // Initialize the new fields to undefined. + for (int i = 0; i < JSObject::kFieldsAdded; ++i) { + values.push_back(jsgraph()->UndefinedConstant()); + } + // Allocate and initialize the new properties. + effect = graph()->NewNode( + common()->BeginRegion(RegionObservability::kNotObservable), effect); + Node* new_properties = effect = graph()->NewNode( + simplified()->Allocate(Type::OtherInternal(), NOT_TENURED), + jsgraph()->Constant(FixedArray::SizeFor(new_length)), effect, control); + effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), + new_properties, jsgraph()->FixedArrayMapConstant(), + effect, control); + effect = graph()->NewNode( + simplified()->StoreField(AccessBuilder::ForFixedArrayLength()), + new_properties, jsgraph()->Constant(new_length), effect, control); + for (int i = 0; i < new_length; ++i) { + effect = graph()->NewNode( + simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), + new_properties, values[i], effect, control); + } + return graph()->NewNode(common()->FinishRegion(), new_properties, effect); +} + void JSNativeContextSpecialization::AssumePrototypesStable( std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) { // Determine actual holder and perform prototype chain checks. |