5 #include "src/compiler/js-native-context-specialization.h" 7 #include "src/accessors.h" 8 #include "src/api-inl.h" 9 #include "src/code-factory.h" 10 #include "src/compiler/access-builder.h" 11 #include "src/compiler/access-info.h" 12 #include "src/compiler/allocation-builder.h" 13 #include "src/compiler/compilation-dependencies.h" 14 #include "src/compiler/js-graph.h" 15 #include "src/compiler/js-operator.h" 16 #include "src/compiler/linkage.h" 17 #include "src/compiler/node-matchers.h" 18 #include "src/compiler/property-access-builder.h" 19 #include "src/compiler/type-cache.h" 21 #include "src/feedback-vector.h" 22 #include "src/field-index-inl.h" 23 #include "src/isolate-inl.h" 24 #include "src/objects/js-array-buffer-inl.h" 25 #include "src/objects/js-array-inl.h" 26 #include "src/objects/templates.h" 27 #include "src/string-constants.h" 28 #include "src/vector-slot-pair.h" 36 #ifndef V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP 37 #define V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP 64 42 bool HasNumberMaps(JSHeapBroker* broker, MapHandles
const& maps) {
43 for (
auto map : maps) {
44 MapRef map_ref(broker, map);
45 if (map_ref.IsHeapNumberMap())
return true;
50 bool HasOnlyJSArrayMaps(JSHeapBroker* broker, MapHandles
const& maps) {
51 for (
auto map : maps) {
52 MapRef map_ref(broker, map);
53 if (!map_ref.IsJSArrayMap())
return false;
60 JSNativeContextSpecialization::JSNativeContextSpecialization(
61 Editor* editor, JSGraph* jsgraph, JSHeapBroker* broker, Flags flags,
62 Handle<Context> native_context, CompilationDependencies* dependencies,
63 Zone* zone, Zone* shared_zone)
64 : AdvancedReducer(editor),
68 global_object_(native_context->global_object(), jsgraph->isolate()),
69 global_proxy_(JSGlobalProxy::cast(native_context->global_proxy()),
71 dependencies_(dependencies),
73 shared_zone_(shared_zone),
74 type_cache_(TypeCache::Get()) {}
76 Reduction JSNativeContextSpecialization::Reduce(Node* node) {
77 switch (node->opcode()) {
78 case IrOpcode::kJSAdd:
79 return ReduceJSAdd(node);
80 case IrOpcode::kJSAsyncFunctionEnter:
81 return ReduceJSAsyncFunctionEnter(node);
82 case IrOpcode::kJSAsyncFunctionReject:
83 return ReduceJSAsyncFunctionReject(node);
84 case IrOpcode::kJSAsyncFunctionResolve:
85 return ReduceJSAsyncFunctionResolve(node);
86 case IrOpcode::kJSGetSuperConstructor:
87 return ReduceJSGetSuperConstructor(node);
88 case IrOpcode::kJSInstanceOf:
89 return ReduceJSInstanceOf(node);
90 case IrOpcode::kJSHasInPrototypeChain:
91 return ReduceJSHasInPrototypeChain(node);
92 case IrOpcode::kJSOrdinaryHasInstance:
93 return ReduceJSOrdinaryHasInstance(node);
94 case IrOpcode::kJSPromiseResolve:
95 return ReduceJSPromiseResolve(node);
96 case IrOpcode::kJSResolvePromise:
97 return ReduceJSResolvePromise(node);
98 case IrOpcode::kJSLoadContext:
99 return ReduceJSLoadContext(node);
100 case IrOpcode::kJSLoadGlobal:
101 return ReduceJSLoadGlobal(node);
102 case IrOpcode::kJSStoreGlobal:
103 return ReduceJSStoreGlobal(node);
104 case IrOpcode::kJSLoadNamed:
105 return ReduceJSLoadNamed(node);
106 case IrOpcode::kJSStoreNamed:
107 return ReduceJSStoreNamed(node);
108 case IrOpcode::kJSLoadProperty:
109 return ReduceJSLoadProperty(node);
110 case IrOpcode::kJSStoreProperty:
111 return ReduceJSStoreProperty(node);
112 case IrOpcode::kJSStoreNamedOwn:
113 return ReduceJSStoreNamedOwn(node);
114 case IrOpcode::kJSStoreDataPropertyInLiteral:
115 return ReduceJSStoreDataPropertyInLiteral(node);
116 case IrOpcode::kJSStoreInArrayLiteral:
117 return ReduceJSStoreInArrayLiteral(node);
118 case IrOpcode::kJSToObject:
119 return ReduceJSToObject(node);
120 case IrOpcode::kJSToString:
121 return ReduceJSToString(node);
129 base::Optional<size_t> JSNativeContextSpecialization::GetMaxStringLength(
130 JSHeapBroker* broker, Node* node) {
131 if (node->opcode() == IrOpcode::kDelayedStringConstant) {
132 return StringConstantBaseOf(node->op())->GetMaxStringConstantLength();
135 HeapObjectMatcher matcher(node);
136 if (matcher.HasValue() && matcher.Ref(broker).IsString()) {
137 StringRef input = matcher.Ref(broker).AsString();
138 return input.length();
141 NumberMatcher number_matcher(node);
142 if (number_matcher.HasValue()) {
143 return kBase10MaximalLength + 1;
148 return base::nullopt;
151 Reduction JSNativeContextSpecialization::ReduceJSToString(Node* node) {
152 DCHECK_EQ(IrOpcode::kJSToString, node->opcode());
153 Node*
const input = node->InputAt(0);
156 HeapObjectMatcher matcher(input);
157 if (matcher.HasValue() && matcher.Ref(broker()).IsString()) {
158 reduction = Changed(input);
159 ReplaceWithValue(node, reduction.replacement());
167 NumberMatcher number_matcher(input);
168 if (number_matcher.HasValue()) {
169 const StringConstantBase* base =
170 new (shared_zone()) NumberToStringConstant(number_matcher.Value());
172 Replace(graph()->NewNode(common()->DelayedStringConstant(base)));
173 ReplaceWithValue(node, reduction.replacement());
180 const StringConstantBase*
181 JSNativeContextSpecialization::CreateDelayedStringConstant(Node* node) {
182 if (node->opcode() == IrOpcode::kDelayedStringConstant) {
183 return StringConstantBaseOf(node->op());
185 NumberMatcher number_matcher(node);
186 if (number_matcher.HasValue()) {
187 return new (shared_zone()) NumberToStringConstant(number_matcher.Value());
189 HeapObjectMatcher matcher(node);
190 if (matcher.HasValue() && matcher.Ref(broker()).IsString()) {
191 StringRef s = matcher.Ref(broker()).AsString();
192 return new (shared_zone())
193 StringLiteral(s.object(),
static_cast<size_t>(s.length()));
202 bool IsStringConstant(JSHeapBroker* broker, Node* node) {
203 if (node->opcode() == IrOpcode::kDelayedStringConstant) {
207 HeapObjectMatcher matcher(node);
208 return matcher.HasValue() && matcher.Ref(broker).IsString();
212 Reduction JSNativeContextSpecialization::ReduceJSAsyncFunctionEnter(
214 DCHECK_EQ(IrOpcode::kJSAsyncFunctionEnter, node->opcode());
215 Node* closure = NodeProperties::GetValueInput(node, 0);
216 Node* receiver = NodeProperties::GetValueInput(node, 1);
217 Node* context = NodeProperties::GetContextInput(node);
218 Node* frame_state = NodeProperties::GetFrameStateInput(node);
219 Node* effect = NodeProperties::GetEffectInput(node);
220 Node* control = NodeProperties::GetControlInput(node);
221 if (!isolate()->IsPromiseHookProtectorIntact())
return NoChange();
224 dependencies()->DependOnProtector(
225 PropertyCellRef(broker(), factory()->promise_hook_protector()));
228 Node* promise = effect =
229 graph()->NewNode(javascript()->CreatePromise(), context, effect);
233 Handle<SharedFunctionInfo> shared =
234 FrameStateInfoOf(frame_state->op()).shared_info().ToHandleChecked();
235 DCHECK(shared->is_compiled());
236 int register_count = shared->internal_formal_parameter_count() +
237 shared->GetBytecodeArray()->register_count();
238 Node* value = effect =
239 graph()->NewNode(javascript()->CreateAsyncFunctionObject(register_count),
240 closure, receiver, promise, context, effect, control);
241 ReplaceWithValue(node, value, effect, control);
242 return Replace(value);
245 Reduction JSNativeContextSpecialization::ReduceJSAsyncFunctionReject(
247 DCHECK_EQ(IrOpcode::kJSAsyncFunctionReject, node->opcode());
248 Node* async_function_object = NodeProperties::GetValueInput(node, 0);
249 Node* reason = NodeProperties::GetValueInput(node, 1);
250 Node* context = NodeProperties::GetContextInput(node);
251 Node* frame_state = NodeProperties::GetFrameStateInput(node);
252 Node* effect = NodeProperties::GetEffectInput(node);
253 Node* control = NodeProperties::GetControlInput(node);
254 if (!isolate()->IsPromiseHookProtectorIntact())
return NoChange();
257 dependencies()->DependOnProtector(
258 PropertyCellRef(broker(), factory()->promise_hook_protector()));
261 Node* promise = effect = graph()->NewNode(
262 simplified()->LoadField(AccessBuilder::ForJSAsyncFunctionObjectPromise()),
263 async_function_object, effect, control);
269 Node* parameters[] = {promise};
270 frame_state = CreateStubBuiltinContinuationFrameState(
271 jsgraph(), Builtins::kAsyncFunctionLazyDeoptContinuation, context,
272 parameters, arraysize(parameters), frame_state,
273 ContinuationFrameStateMode::LAZY);
277 Node* debug_event = jsgraph()->FalseConstant();
278 effect = graph()->NewNode(javascript()->RejectPromise(), promise, reason,
279 debug_event, context, frame_state, effect, control);
280 ReplaceWithValue(node, promise, effect, control);
281 return Replace(promise);
284 Reduction JSNativeContextSpecialization::ReduceJSAsyncFunctionResolve(
286 DCHECK_EQ(IrOpcode::kJSAsyncFunctionResolve, node->opcode());
287 Node* async_function_object = NodeProperties::GetValueInput(node, 0);
288 Node* value = NodeProperties::GetValueInput(node, 1);
289 Node* context = NodeProperties::GetContextInput(node);
290 Node* frame_state = NodeProperties::GetFrameStateInput(node);
291 Node* effect = NodeProperties::GetEffectInput(node);
292 Node* control = NodeProperties::GetControlInput(node);
293 if (!isolate()->IsPromiseHookProtectorIntact())
return NoChange();
296 dependencies()->DependOnProtector(
297 PropertyCellRef(broker(), factory()->promise_hook_protector()));
300 Node* promise = effect = graph()->NewNode(
301 simplified()->LoadField(AccessBuilder::ForJSAsyncFunctionObjectPromise()),
302 async_function_object, effect, control);
308 Node* parameters[] = {promise};
309 frame_state = CreateStubBuiltinContinuationFrameState(
310 jsgraph(), Builtins::kAsyncFunctionLazyDeoptContinuation, context,
311 parameters, arraysize(parameters), frame_state,
312 ContinuationFrameStateMode::LAZY);
314 effect = graph()->NewNode(javascript()->ResolvePromise(), promise, value,
315 context, frame_state, effect, control);
316 ReplaceWithValue(node, promise, effect, control);
317 return Replace(promise);
320 Reduction JSNativeContextSpecialization::ReduceJSAdd(Node* node) {
325 DCHECK_EQ(IrOpcode::kJSAdd, node->opcode());
327 Node*
const lhs = node->InputAt(0);
328 Node*
const rhs = node->InputAt(1);
330 base::Optional<size_t> lhs_len = GetMaxStringLength(broker(), lhs);
331 base::Optional<size_t> rhs_len = GetMaxStringLength(broker(), rhs);
332 if (!lhs_len || !rhs_len) {
338 if (*lhs_len + *rhs_len <= String::kMaxLength &&
339 (IsStringConstant(broker(), lhs) || IsStringConstant(broker(), rhs))) {
340 const StringConstantBase* left = CreateDelayedStringConstant(lhs);
341 const StringConstantBase* right = CreateDelayedStringConstant(rhs);
342 const StringConstantBase* cons =
343 new (shared_zone()) StringCons(left, right);
345 Node* reduced = graph()->NewNode(common()->DelayedStringConstant(cons));
346 ReplaceWithValue(node, reduced);
347 return Replace(reduced);
353 Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor(
355 DCHECK_EQ(IrOpcode::kJSGetSuperConstructor, node->opcode());
356 Node* constructor = NodeProperties::GetValueInput(node, 0);
359 HeapObjectMatcher m(constructor);
360 if (!m.HasValue())
return NoChange();
361 JSFunctionRef
function = m.Ref(broker()).AsJSFunction();
362 MapRef function_map =
function.map();
364 function_map.SerializePrototype();
365 ObjectRef function_prototype = function_map.prototype();
370 if (function_map.is_stable() && function_prototype.IsHeapObject() &&
371 function_prototype.AsHeapObject().map().is_constructor()) {
372 dependencies()->DependOnStableMap(function_map);
373 Node* value = jsgraph()->Constant(function_prototype);
374 ReplaceWithValue(node, value);
375 return Replace(value);
381 Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
382 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
383 FeedbackParameter
const& p = FeedbackParameterOf(node->op());
384 Node*
object = NodeProperties::GetValueInput(node, 0);
385 Node* constructor = NodeProperties::GetValueInput(node, 1);
386 Node* context = NodeProperties::GetContextInput(node);
387 Node* effect = NodeProperties::GetEffectInput(node);
388 Node* frame_state = NodeProperties::GetFrameStateInput(node);
389 Node* control = NodeProperties::GetControlInput(node);
393 Handle<JSObject> receiver;
394 HeapObjectMatcher m(constructor);
395 if (m.HasValue() && m.Value()->IsJSObject()) {
396 receiver = Handle<JSObject>::cast(m.Value());
397 }
else if (p.feedback().IsValid()) {
398 FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
399 if (!nexus.GetConstructorFeedback().ToHandle(&receiver))
return NoChange();
403 Handle<Map> receiver_map(receiver->map(), isolate());
406 PropertyAccessInfo access_info;
407 AccessInfoFactory access_info_factory(
408 broker(), dependencies(), native_context().
object(), graph()->zone());
409 if (!access_info_factory.ComputePropertyAccessInfo(
410 receiver_map, factory()->has_instance_symbol(), AccessMode::kLoad,
414 DCHECK_EQ(access_info.receiver_maps().size(), 1);
415 DCHECK_EQ(access_info.receiver_maps()[0].address(), receiver_map.address());
417 PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
419 if (access_info.IsNotFound()) {
422 if (!receiver_map->is_callable())
return NoChange();
425 Handle<JSObject> holder;
426 if (access_info.holder().ToHandle(&holder)) {
427 dependencies()->DependOnStablePrototypeChains(
428 broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
432 access_builder.BuildCheckMaps(constructor, &effect, control,
433 access_info.receiver_maps());
436 NodeProperties::ReplaceValueInput(node, constructor, 0);
437 NodeProperties::ReplaceValueInput(node,
object, 1);
438 NodeProperties::ReplaceEffectInput(node, effect);
439 NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance());
440 Reduction
const reduction = ReduceJSOrdinaryHasInstance(node);
441 return reduction.Changed() ? reduction : Changed(node);
444 if (access_info.IsDataConstant() || access_info.IsDataConstantField()) {
446 Handle<JSObject> holder;
447 bool found_on_proto = access_info.holder().ToHandle(&holder);
448 if (!found_on_proto) holder = receiver;
450 Handle<Object> constant;
451 if (access_info.IsDataConstant()) {
452 DCHECK(!FLAG_track_constant_fields);
453 constant = access_info.constant();
455 DCHECK(FLAG_track_constant_fields);
456 DCHECK(access_info.IsDataConstantField());
457 FieldIndex field_index = access_info.field_index();
458 constant = JSObject::FastPropertyAt(holder, Representation::Tagged(),
460 if (!constant->IsCallable()) {
466 MapRef holder_map(broker(), handle(holder->map(), isolate()));
467 Handle<DescriptorArray> descriptors(
468 holder_map.object()->instance_descriptors(), isolate());
469 int descriptor_index = descriptors->Search(
470 *(factory()->has_instance_symbol()), *(holder_map.object()));
471 CHECK_NE(descriptor_index, DescriptorArray::kNotFound);
472 holder_map.SerializeOwnDescriptors();
473 dependencies()->DependOnFieldType(holder_map, descriptor_index);
476 if (found_on_proto) {
477 dependencies()->DependOnStablePrototypeChains(
478 broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
481 DCHECK(constant->IsCallable());
485 access_builder.BuildCheckValue(constructor, &effect, control, receiver);
488 access_builder.BuildCheckMaps(constructor, &effect, control,
489 access_info.receiver_maps());
497 Node* continuation_frame_state = CreateStubBuiltinContinuationFrameState(
498 jsgraph(), Builtins::kToBooleanLazyDeoptContinuation, context,
nullptr,
499 0, frame_state, ContinuationFrameStateMode::LAZY);
502 Node* target = jsgraph()->Constant(constant);
503 node->InsertInput(graph()->zone(), 0, target);
504 node->ReplaceInput(1, constructor);
505 node->ReplaceInput(2,
object);
506 node->ReplaceInput(4, continuation_frame_state);
507 node->ReplaceInput(5, effect);
508 NodeProperties::ChangeOp(
509 node, javascript()->Call(3, CallFrequency(), VectorSlotPair(),
510 ConvertReceiverMode::kNotNullOrUndefined));
513 Node* value = graph()->NewNode(simplified()->ToBoolean(), node);
514 for (Edge edge : node->use_edges()) {
515 if (NodeProperties::IsValueEdge(edge) && edge.from() != value) {
516 edge.UpdateTo(value);
517 Revisit(edge.from());
520 return Changed(node);
526 JSNativeContextSpecialization::InferHasInPrototypeChainResult
527 JSNativeContextSpecialization::InferHasInPrototypeChain(
528 Node* receiver, Node* effect, Handle<HeapObject> prototype) {
529 ZoneHandleSet<Map> receiver_maps;
530 NodeProperties::InferReceiverMapsResult result =
531 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
533 if (result == NodeProperties::kNoReceiverMaps)
return kMayBeInPrototypeChain;
539 for (
size_t i = 0;
i < receiver_maps.size(); ++
i) {
540 Handle<Map> receiver_map = receiver_maps[
i];
541 if (receiver_map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
542 return kMayBeInPrototypeChain;
544 if (result == NodeProperties::kUnreliableReceiverMaps) {
549 if (!receiver_map->is_stable()) {
550 return kMayBeInPrototypeChain;
553 for (PrototypeIterator j(isolate(), receiver_map);; j.Advance()) {
558 Handle<HeapObject>
const current =
559 PrototypeIterator::GetCurrent<HeapObject>(j);
560 if (current.is_identical_to(prototype)) {
564 if (!current->map()->is_stable() ||
565 current->map()->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
566 return kMayBeInPrototypeChain;
570 DCHECK_IMPLIES(all, !none);
571 DCHECK_IMPLIES(none, !all);
573 if (all)
return kIsInPrototypeChain;
574 if (none)
return kIsNotInPrototypeChain;
575 return kMayBeInPrototypeChain;
578 Reduction JSNativeContextSpecialization::ReduceJSHasInPrototypeChain(
580 DCHECK_EQ(IrOpcode::kJSHasInPrototypeChain, node->opcode());
581 Node* value = NodeProperties::GetValueInput(node, 0);
582 Node* prototype = NodeProperties::GetValueInput(node, 1);
583 Node* effect = NodeProperties::GetEffectInput(node);
587 HeapObjectMatcher m(prototype);
589 InferHasInPrototypeChainResult result =
590 InferHasInPrototypeChain(value, effect, m.Value());
591 if (result != kMayBeInPrototypeChain) {
592 Node* value = jsgraph()->BooleanConstant(result == kIsInPrototypeChain);
593 ReplaceWithValue(node, value);
594 return Replace(value);
601 Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance(
603 DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode());
604 Node* constructor = NodeProperties::GetValueInput(node, 0);
605 Node*
object = NodeProperties::GetValueInput(node, 1);
608 HeapObjectMatcher m(constructor);
609 if (!m.HasValue())
return NoChange();
612 if (m.Value()->IsJSBoundFunction()) {
616 Handle<JSBoundFunction>
function = Handle<JSBoundFunction>::cast(m.Value());
617 Handle<JSReceiver> bound_target_function(function->bound_target_function(),
619 NodeProperties::ReplaceValueInput(node,
object, 0);
620 NodeProperties::ReplaceValueInput(
621 node, jsgraph()->HeapConstant(bound_target_function), 1);
622 NodeProperties::ChangeOp(node, javascript()->InstanceOf(VectorSlotPair()));
623 Reduction
const reduction = ReduceJSInstanceOf(node);
624 return reduction.Changed() ? reduction : Changed(node);
628 if (m.Value()->IsJSFunction()) {
629 JSFunctionRef
function = m.Ref(broker()).AsJSFunction();
632 function.Serialize();
635 if (!
function.map().has_prototype_slot() || !
function.has_prototype() ||
636 function.PrototypeRequiresRuntimeLookup()) {
639 ObjectRef prototype = dependencies()->DependOnPrototypeProperty(
function);
640 Node* prototype_constant = jsgraph()->Constant(prototype);
643 NodeProperties::ReplaceValueInput(node,
object, 0);
644 NodeProperties::ReplaceValueInput(node, prototype_constant, 1);
645 NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain());
646 Reduction
const reduction = ReduceJSHasInPrototypeChain(node);
647 return reduction.Changed() ? reduction : Changed(node);
654 Reduction JSNativeContextSpecialization::ReduceJSPromiseResolve(Node* node) {
655 DCHECK_EQ(IrOpcode::kJSPromiseResolve, node->opcode());
656 Node* constructor = NodeProperties::GetValueInput(node, 0);
657 Node* value = NodeProperties::GetValueInput(node, 1);
658 Node* context = NodeProperties::GetContextInput(node);
659 Node* frame_state = NodeProperties::GetFrameStateInput(node);
660 Node* effect = NodeProperties::GetEffectInput(node);
661 Node* control = NodeProperties::GetControlInput(node);
663 if (!isolate()->IsPromiseHookProtectorIntact()) {
668 HeapObjectMatcher m(constructor);
670 !m.Ref(broker()).equals(broker()->native_context().promise_function())) {
675 ZoneHandleSet<Map> value_maps;
676 NodeProperties::InferReceiverMapsResult result =
677 NodeProperties::InferReceiverMaps(broker(), value, effect, &value_maps);
678 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
679 DCHECK_NE(0, value_maps.size());
682 for (Handle<Map>
const value_map : value_maps) {
683 if (value_map->IsJSPromiseMap())
return NoChange();
687 dependencies()->DependOnProtector(
688 PropertyCellRef(broker(), factory()->promise_hook_protector()));
691 Node* promise = effect =
692 graph()->NewNode(javascript()->CreatePromise(), context, effect);
693 effect = graph()->NewNode(javascript()->ResolvePromise(), promise, value,
694 context, frame_state, effect, control);
695 ReplaceWithValue(node, promise, effect, control);
696 return Replace(promise);
700 Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
701 DCHECK_EQ(IrOpcode::kJSResolvePromise, node->opcode());
702 Node* promise = NodeProperties::GetValueInput(node, 0);
703 Node* resolution = NodeProperties::GetValueInput(node, 1);
704 Node* context = NodeProperties::GetContextInput(node);
705 Node* effect = NodeProperties::GetEffectInput(node);
706 Node* control = NodeProperties::GetControlInput(node);
709 ZoneHandleSet<Map> resolution_maps;
710 NodeProperties::InferReceiverMapsResult result =
711 NodeProperties::InferReceiverMaps(broker(), resolution, effect,
713 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
714 DCHECK_NE(0, resolution_maps.size());
718 if (result == NodeProperties::kUnreliableReceiverMaps) {
719 for (Handle<Map> resolution_map : resolution_maps) {
720 if (!resolution_map->is_stable())
return NoChange();
725 PropertyAccessInfo access_info;
726 AccessInfoFactory access_info_factory(
727 broker(), dependencies(), native_context().
object(), graph()->zone());
728 if (!access_info_factory.ComputePropertyAccessInfo(
729 MapHandles(resolution_maps.begin(), resolution_maps.end()),
730 factory()->then_string(), AccessMode::kLoad, &access_info)) {
736 if (!access_info.IsNotFound())
return NoChange();
737 PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
740 Handle<JSObject> holder;
741 if (access_info.holder().ToHandle(&holder)) {
742 dependencies()->DependOnStablePrototypeChains(
743 broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
747 if (result == NodeProperties::kUnreliableReceiverMaps) {
748 for (Handle<Map> resolution_map : resolution_maps) {
749 dependencies()->DependOnStableMap(MapRef(broker(), resolution_map));
754 Node* value = effect =
755 graph()->NewNode(javascript()->FulfillPromise(), promise, resolution,
756 context, effect, control);
757 ReplaceWithValue(node, value, effect, control);
758 return Replace(value);
761 Reduction JSNativeContextSpecialization::ReduceJSLoadContext(Node* node) {
762 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
763 ContextAccess
const& access = ContextAccessOf(node->op());
767 if (access.index() == Context::NATIVE_CONTEXT_INDEX) {
768 Node* value = jsgraph()->Constant(native_context());
769 ReplaceWithValue(node, value);
770 return Replace(value);
777 FieldAccess ForPropertyCellValue(MachineRepresentation representation,
778 Type type, MaybeHandle<Map> map,
780 WriteBarrierKind kind = kFullWriteBarrier;
781 if (representation == MachineRepresentation::kTaggedSigned) {
782 kind = kNoWriteBarrier;
783 }
else if (representation == MachineRepresentation::kTaggedPointer) {
784 kind = kPointerWriteBarrier;
786 MachineType r = MachineType::TypeForRepresentation(representation);
787 FieldAccess access = {
788 kTaggedBase, PropertyCell::kValueOffset, name, map, type, r, kind};
794 Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
795 Node* node, Node* receiver, Node* value, Handle<Name> name,
796 AccessMode access_mode, Node* index) {
797 Node* effect = NodeProperties::GetEffectInput(node);
798 Node* control = NodeProperties::GetControlInput(node);
802 LookupIterator it(isolate(), global_object(), name, LookupIterator::OWN);
803 it.TryLookupCachedProperty();
804 if (it.state() != LookupIterator::DATA)
return NoChange();
805 if (!it.GetHolder<JSObject>()->IsJSGlobalObject())
return NoChange();
806 Handle<PropertyCell> property_cell = it.GetPropertyCell();
807 PropertyDetails property_details = property_cell->property_details();
808 Handle<Object> property_cell_value(property_cell->value(), isolate());
809 PropertyCellType property_cell_type = property_details.cell_type();
812 if (access_mode == AccessMode::kStore) {
813 if (property_details.IsReadOnly()) {
816 }
else if (property_cell_type == PropertyCellType::kUndefined) {
819 }
else if (property_cell_type == PropertyCellType::kConstantType) {
822 if (property_cell_value->IsHeapObject() &&
823 !Handle<HeapObject>::cast(property_cell_value)->map()->is_stable()) {
830 if (index !=
nullptr) {
831 effect = BuildCheckEqualsName(name, index, effect, control);
837 if (receiver !=
nullptr) {
838 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
839 jsgraph()->HeapConstant(global_proxy()));
840 effect = graph()->NewNode(
841 simplified()->CheckIf(DeoptimizeReason::kReceiverNotAGlobalProxy),
842 check, effect, control);
845 if (access_mode == AccessMode::kLoad) {
848 if (!property_details.IsConfigurable() && property_details.IsReadOnly()) {
849 value = jsgraph()->Constant(property_cell_value);
854 if (property_details.cell_type() != PropertyCellType::kMutable ||
855 property_details.IsConfigurable()) {
856 dependencies()->DependOnGlobalProperty(
857 PropertyCellRef(broker(), property_cell));
861 if (property_details.cell_type() == PropertyCellType::kConstant ||
862 property_details.cell_type() == PropertyCellType::kUndefined) {
863 value = jsgraph()->Constant(property_cell_value);
865 !property_cell_value.is_identical_to(factory()->the_hole_value()));
868 MaybeHandle<Map> map;
869 Type property_cell_value_type = Type::NonInternal();
870 MachineRepresentation representation = MachineRepresentation::kTagged;
871 if (property_details.cell_type() == PropertyCellType::kConstantType) {
873 if (property_cell_value->IsSmi()) {
874 property_cell_value_type = Type::SignedSmall();
875 representation = MachineRepresentation::kTaggedSigned;
876 }
else if (property_cell_value->IsNumber()) {
877 property_cell_value_type = Type::Number();
878 representation = MachineRepresentation::kTaggedPointer;
880 MapRef property_cell_value_map(
881 broker(), handle(HeapObject::cast(*property_cell_value)->map(),
883 property_cell_value_type = Type::For(property_cell_value_map);
884 representation = MachineRepresentation::kTaggedPointer;
889 if (property_cell_value_map.is_stable()) {
890 dependencies()->DependOnStableMap(property_cell_value_map);
891 map = property_cell_value_map.object();
895 value = effect = graph()->NewNode(
896 simplified()->LoadField(ForPropertyCellValue(
897 representation, property_cell_value_type, map, name)),
898 jsgraph()->HeapConstant(property_cell), effect, control);
902 DCHECK_EQ(AccessMode::kStore, access_mode);
903 DCHECK(!property_details.IsReadOnly());
904 switch (property_details.cell_type()) {
905 case PropertyCellType::kUndefined: {
909 case PropertyCellType::kConstant: {
912 dependencies()->DependOnGlobalProperty(
913 PropertyCellRef(broker(), property_cell));
915 graph()->NewNode(simplified()->ReferenceEqual(), value,
916 jsgraph()->Constant(property_cell_value));
917 effect = graph()->NewNode(
918 simplified()->CheckIf(DeoptimizeReason::kValueMismatch), check,
922 case PropertyCellType::kConstantType: {
926 dependencies()->DependOnGlobalProperty(
927 PropertyCellRef(broker(), property_cell));
928 Type property_cell_value_type;
929 MachineRepresentation representation = MachineRepresentation::kTagged;
930 if (property_cell_value->IsHeapObject()) {
933 Handle<Map> property_cell_value_map(
934 Handle<HeapObject>::cast(property_cell_value)->map(), isolate());
935 DCHECK(property_cell_value_map->is_stable());
936 dependencies()->DependOnStableMap(
937 MapRef(broker(), property_cell_value_map));
940 value = effect = graph()->NewNode(simplified()->CheckHeapObject(),
941 value, effect, control);
945 graph()->NewNode(simplified()->CheckMaps(
946 CheckMapsFlag::kNone,
947 ZoneHandleSet<Map>(property_cell_value_map)),
948 value, effect, control);
949 property_cell_value_type = Type::OtherInternal();
950 representation = MachineRepresentation::kTaggedPointer;
953 value = effect = graph()->NewNode(
954 simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
955 property_cell_value_type = Type::SignedSmall();
956 representation = MachineRepresentation::kTaggedSigned;
958 effect = graph()->NewNode(simplified()->StoreField(ForPropertyCellValue(
959 representation, property_cell_value_type,
960 MaybeHandle<Map>(), name)),
961 jsgraph()->HeapConstant(property_cell), value,
965 case PropertyCellType::kMutable: {
968 dependencies()->DependOnGlobalProperty(
969 PropertyCellRef(broker(), property_cell));
970 effect = graph()->NewNode(
971 simplified()->StoreField(ForPropertyCellValue(
972 MachineRepresentation::kTagged, Type::NonInternal(),
973 MaybeHandle<Map>(), name)),
974 jsgraph()->HeapConstant(property_cell), value, effect, control);
980 ReplaceWithValue(node, value, effect, control);
981 return Replace(value);
984 Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) {
985 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode());
986 NameRef name(broker(), LoadGlobalParametersOf(node->op()).name());
987 Node* effect = NodeProperties::GetEffectInput(node);
990 base::Optional<ScriptContextTableRef::LookupResult> result =
991 native_context().script_context_table().lookup(name);
993 ObjectRef contents = result->context.get(result->index);
994 if (contents.IsHeapObject() &&
995 contents.AsHeapObject().map().oddball_type() == OddballType::kHole) {
998 Node* context = jsgraph()->Constant(result->context);
999 Node* value = effect = graph()->NewNode(
1000 javascript()->LoadContext(0, result->index, result->immutable), context,
1002 ReplaceWithValue(node, value, effect);
1003 return Replace(value);
1007 return ReduceGlobalAccess(node,
nullptr,
nullptr, name.object(),
1011 Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) {
1012 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode());
1013 NameRef name(broker(), StoreGlobalParametersOf(node->op()).name());
1014 Node* value = NodeProperties::GetValueInput(node, 0);
1015 Node* effect = NodeProperties::GetEffectInput(node);
1016 Node* control = NodeProperties::GetControlInput(node);
1019 base::Optional<ScriptContextTableRef::LookupResult> result =
1020 native_context().script_context_table().lookup(name);
1022 ObjectRef contents = result->context.get(result->index);
1023 if ((contents.IsHeapObject() &&
1024 contents.AsHeapObject().map().oddball_type() == OddballType::kHole) ||
1025 result->immutable) {
1028 Node* context = jsgraph()->Constant(result->context);
1029 effect = graph()->NewNode(javascript()->StoreContext(0, result->index),
1030 value, context, effect, control);
1031 ReplaceWithValue(node, value, effect, control);
1032 return Replace(value);
1036 return ReduceGlobalAccess(node,
nullptr, value, name.object(),
1037 AccessMode::kStore);
1040 Reduction JSNativeContextSpecialization::ReduceNamedAccess(
1041 Node* node, Node* value, MapHandles
const& receiver_maps, Handle<Name> name,
1042 AccessMode access_mode, Node* index) {
1043 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
1044 node->opcode() == IrOpcode::kJSStoreNamed ||
1045 node->opcode() == IrOpcode::kJSLoadProperty ||
1046 node->opcode() == IrOpcode::kJSStoreProperty ||
1047 node->opcode() == IrOpcode::kJSStoreNamedOwn);
1048 Node* receiver = NodeProperties::GetValueInput(node, 0);
1049 Node* context = NodeProperties::GetContextInput(node);
1050 Node* frame_state = NodeProperties::GetFrameStateInput(node);
1051 Node* effect = NodeProperties::GetEffectInput(node);
1052 Node* control = NodeProperties::GetControlInput(node);
1057 if (receiver_maps.size() == 1) {
1058 Handle<Map> receiver_map = receiver_maps.front();
1059 if (receiver_map->IsJSGlobalProxyMap()) {
1060 Object* maybe_constructor = receiver_map->GetConstructor();
1062 if (maybe_constructor->IsJSFunction() &&
1063 JSFunction::cast(maybe_constructor)->native_context() ==
1064 *native_context().object()) {
1065 return ReduceGlobalAccess(node, receiver, value, name, access_mode,
1072 AccessInfoFactory access_info_factory(
1073 broker(), dependencies(), native_context().
object(), graph()->zone());
1074 ZoneVector<PropertyAccessInfo> access_infos(zone());
1075 if (!access_info_factory.ComputePropertyAccessInfos(
1076 receiver_maps, name, access_mode, &access_infos)) {
1081 if (access_infos.empty()) {
1082 return ReduceSoftDeoptimize(
1083 node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
1087 if (index !=
nullptr) {
1088 effect = BuildCheckEqualsName(name, index, effect, control);
1092 ZoneVector<Node*> if_exception_nodes(zone());
1093 ZoneVector<Node*>* if_exceptions =
nullptr;
1094 Node* if_exception =
nullptr;
1095 if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
1096 if_exceptions = &if_exception_nodes;
1099 PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
1102 if (access_infos.size() == 1) {
1103 PropertyAccessInfo access_info = access_infos.front();
1106 if (!access_builder.TryBuildStringCheck(access_info.receiver_maps(),
1107 &receiver, &effect, control) &&
1108 !access_builder.TryBuildNumberCheck(access_info.receiver_maps(),
1109 &receiver, &effect, control)) {
1110 if (HasNumberMaps(broker(), access_info.receiver_maps())) {
1114 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
1115 Node* branch = graph()->NewNode(common()->Branch(), check, control);
1117 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1118 Node* etrue = effect;
1120 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1121 Node* efalse = effect;
1123 access_builder.BuildCheckMaps(receiver, &efalse, if_false,
1124 access_info.receiver_maps());
1127 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1129 graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
1132 access_builder.BuildCheckHeapObject(receiver, &effect, control);
1133 access_builder.BuildCheckMaps(receiver, &effect, control,
1134 access_info.receiver_maps());
1139 ValueEffectControl continuation = BuildPropertyAccess(
1140 receiver, value, context, frame_state, effect, control, name,
1141 if_exceptions, access_info, access_mode);
1142 value = continuation.value();
1143 effect = continuation.effect();
1144 control = continuation.control();
1148 ZoneVector<Node*> values(zone());
1149 ZoneVector<Node*> effects(zone());
1150 ZoneVector<Node*> controls(zone());
1153 bool receiverissmi_possible =
false;
1154 for (PropertyAccessInfo
const& access_info : access_infos) {
1155 if (HasNumberMaps(broker(), access_info.receiver_maps())) {
1156 receiverissmi_possible =
true;
1162 Node* receiverissmi_control =
nullptr;
1163 Node* receiverissmi_effect = effect;
1164 if (receiverissmi_possible) {
1165 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
1166 Node* branch = graph()->NewNode(common()->Branch(), check, control);
1167 control = graph()->NewNode(common()->IfFalse(), branch);
1168 receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
1169 receiverissmi_effect = effect;
1172 access_builder.BuildCheckHeapObject(receiver, &effect, control);
1176 Node* fallthrough_control = control;
1177 for (
size_t j = 0; j < access_infos.size(); ++j) {
1178 PropertyAccessInfo
const& access_info = access_infos[j];
1179 Node* this_value = value;
1180 Node* this_receiver = receiver;
1181 Node* this_effect = effect;
1182 Node* this_control = fallthrough_control;
1185 MapHandles
const& receiver_maps = access_info.receiver_maps();
1189 bool insert_map_guard =
true;
1192 if (j == access_infos.size() - 1) {
1195 access_builder.BuildCheckMaps(receiver, &this_effect, this_control,
1197 fallthrough_control =
nullptr;
1202 insert_map_guard =
false;
1205 ZoneHandleSet<Map> maps;
1206 for (Handle<Map> map : receiver_maps) {
1207 maps.insert(map, graph()->zone());
1209 Node* check = this_effect =
1210 graph()->NewNode(simplified()->CompareMaps(maps), receiver,
1211 this_effect, this_control);
1213 graph()->NewNode(common()->Branch(), check, this_control);
1214 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
1215 this_control = graph()->NewNode(common()->IfTrue(), branch);
1219 if (HasNumberMaps(broker(), receiver_maps)) {
1221 DCHECK_NOT_NULL(receiverissmi_effect);
1222 DCHECK_NOT_NULL(receiverissmi_control);
1223 this_control = graph()->NewNode(common()->Merge(2), this_control,
1224 receiverissmi_control);
1225 this_effect = graph()->NewNode(common()->EffectPhi(2), this_effect,
1226 receiverissmi_effect, this_control);
1227 receiverissmi_effect = receiverissmi_control =
nullptr;
1231 insert_map_guard =
false;
1235 if (insert_map_guard) {
1236 ZoneHandleSet<Map> maps;
1237 for (
auto receiver_map : receiver_maps) {
1238 maps.insert(receiver_map, graph()->zone());
1240 this_effect = graph()->NewNode(simplified()->MapGuard(maps), receiver,
1241 this_effect, this_control);
1248 if (HasOnlyStringMaps(receiver_maps)) {
1249 this_receiver = this_effect =
1250 graph()->NewNode(common()->TypeGuard(Type::String()), receiver,
1251 this_effect, this_control);
1256 ValueEffectControl continuation = BuildPropertyAccess(
1257 this_receiver, this_value, context, frame_state, this_effect,
1258 this_control, name, if_exceptions, access_info, access_mode);
1259 values.push_back(continuation.value());
1260 effects.push_back(continuation.effect());
1261 controls.push_back(continuation.control());
1264 DCHECK_NULL(fallthrough_control);
1267 int const control_count =
static_cast<int>(controls.size());
1268 if (control_count == 0) {
1269 value = effect = control = jsgraph()->Dead();
1270 }
else if (control_count == 1) {
1271 value = values.front();
1272 effect = effects.front();
1273 control = controls.front();
1275 control = graph()->NewNode(common()->Merge(control_count), control_count,
1277 values.push_back(control);
1278 value = graph()->NewNode(
1279 common()->Phi(MachineRepresentation::kTagged, control_count),
1280 control_count + 1, &values.front());
1281 effects.push_back(control);
1282 effect = graph()->NewNode(common()->EffectPhi(control_count),
1283 control_count + 1, &effects.front());
1288 if (!if_exception_nodes.empty()) {
1289 DCHECK_NOT_NULL(if_exception);
1290 DCHECK_EQ(if_exceptions, &if_exception_nodes);
1291 int const if_exception_count =
static_cast<int>(if_exceptions->size());
1292 Node* merge = graph()->NewNode(common()->Merge(if_exception_count),
1293 if_exception_count, &if_exceptions->front());
1294 if_exceptions->push_back(merge);
1296 graph()->NewNode(common()->EffectPhi(if_exception_count),
1297 if_exception_count + 1, &if_exceptions->front());
1298 Node* phi = graph()->NewNode(
1299 common()->Phi(MachineRepresentation::kTagged, if_exception_count),
1300 if_exception_count + 1, &if_exceptions->front());
1301 ReplaceWithValue(if_exception, phi, ephi, merge);
1304 ReplaceWithValue(node, value, effect, control);
1305 return Replace(value);
1308 Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus(
1309 Node* node, Node* value, FeedbackNexus
const& nexus, Handle<Name> name,
1310 AccessMode access_mode) {
1311 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
1312 node->opcode() == IrOpcode::kJSStoreNamed ||
1313 node->opcode() == IrOpcode::kJSStoreNamedOwn);
1314 Node*
const receiver = NodeProperties::GetValueInput(node, 0);
1315 Node*
const effect = NodeProperties::GetEffectInput(node);
1318 HeapObjectMatcher m(receiver);
1319 if (m.HasValue() && m.Value().is_identical_to(global_proxy())) {
1321 return ReduceGlobalAccess(node,
nullptr, value, name, access_mode);
1325 MapHandles receiver_maps;
1326 if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
1328 }
else if (receiver_maps.empty()) {
1329 if (flags() & kBailoutOnUninitialized) {
1330 return ReduceSoftDeoptimize(
1332 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
1336 DCHECK(!nexus.IsUninitialized());
1339 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode);
1342 Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
1343 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
1344 NamedAccess
const& p = NamedAccessOf(node->op());
1345 Node*
const receiver = NodeProperties::GetValueInput(node, 0);
1346 Node*
const value = jsgraph()->Dead();
1349 HeapObjectMatcher m(receiver);
1351 if (m.Value()->IsJSFunction() &&
1352 p.name().is_identical_to(factory()->prototype_string())) {
1354 JSFunctionRef
function = m.Ref(broker()).AsJSFunction();
1357 function.Serialize();
1360 if (!
function.map().has_prototype_slot() || !
function.has_prototype() ||
1361 function.PrototypeRequiresRuntimeLookup()) {
1364 ObjectRef prototype = dependencies()->DependOnPrototypeProperty(
function);
1365 Node* value = jsgraph()->Constant(prototype);
1366 ReplaceWithValue(node, value);
1367 return Replace(value);
1368 }
else if (m.Value()->IsString() &&
1369 p.name().is_identical_to(factory()->length_string())) {
1371 Handle<String>
string = Handle<String>::cast(m.Value());
1372 Node* value = jsgraph()->Constant(string->length());
1373 ReplaceWithValue(node, value);
1374 return Replace(value);
1379 if (!p.feedback().IsValid())
return NoChange();
1380 FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
1383 return ReduceNamedAccessFromNexus(node, value, nexus, p.name(),
1388 Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) {
1389 DCHECK_EQ(IrOpcode::kJSStoreNamed, node->opcode());
1390 NamedAccess
const& p = NamedAccessOf(node->op());
1391 Node*
const value = NodeProperties::GetValueInput(node, 1);
1394 if (!p.feedback().IsValid())
return NoChange();
1395 FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
1398 return ReduceNamedAccessFromNexus(node, value, nexus, p.name(),
1399 AccessMode::kStore);
1402 Reduction JSNativeContextSpecialization::ReduceJSStoreNamedOwn(Node* node) {
1403 DCHECK_EQ(IrOpcode::kJSStoreNamedOwn, node->opcode());
1404 StoreNamedOwnParameters
const& p = StoreNamedOwnParametersOf(node->op());
1405 Node*
const value = NodeProperties::GetValueInput(node, 1);
1408 if (!p.feedback().IsValid())
return NoChange();
1409 FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
1412 return ReduceNamedAccessFromNexus(node, value, nexus, p.name(),
1413 AccessMode::kStoreInLiteral);
1416 Reduction JSNativeContextSpecialization::ReduceElementAccess(
1417 Node* node, Node* index, Node* value, MapHandles
const& receiver_maps,
1418 AccessMode access_mode, KeyedAccessLoadMode load_mode,
1419 KeyedAccessStoreMode store_mode) {
1420 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
1421 node->opcode() == IrOpcode::kJSStoreProperty ||
1422 node->opcode() == IrOpcode::kJSStoreInArrayLiteral);
1423 Node* receiver = NodeProperties::GetValueInput(node, 0);
1424 Node* effect = NodeProperties::GetEffectInput(node);
1425 Node* control = NodeProperties::GetControlInput(node);
1426 Node* frame_state = NodeProperties::FindFrameStateBefore(node);
1429 if (HasOnlyStringMaps(receiver_maps)) {
1431 if (access_mode == AccessMode::kStore)
return NoChange();
1434 receiver = effect = graph()->NewNode(
1435 simplified()->CheckString(VectorSlotPair()), receiver, effect, control);
1438 Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
1442 value = BuildIndexedStringLoad(receiver, index, length, &effect, &control,
1447 AccessInfoFactory access_info_factory(
1448 broker(), dependencies(), native_context().
object(), graph()->zone());
1449 ZoneVector<ElementAccessInfo> access_infos(zone());
1450 if (!access_info_factory.ComputeElementAccessInfos(
1451 receiver_maps, access_mode, &access_infos)) {
1456 if (access_infos.empty()) {
1457 return ReduceSoftDeoptimize(
1459 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
1465 if (access_mode == AccessMode::kStore) {
1469 ZoneVector<Handle<Map>> prototype_maps(zone());
1470 for (ElementAccessInfo
const& access_info : access_infos) {
1471 for (Handle<Map> receiver_map : access_info.receiver_maps()) {
1476 if (IsHoleyOrDictionaryElementsKind(receiver_map->elements_kind()) ||
1477 IsGrowStoreMode(store_mode)) {
1479 for (Handle<Map> map = receiver_map;;) {
1480 Handle<Object> map_prototype(map->prototype(), isolate());
1481 if (map_prototype->IsNull(isolate()))
break;
1482 if (!map_prototype->IsJSObject())
return NoChange();
1483 map = handle(Handle<JSObject>::cast(map_prototype)->map(),
1485 if (!map->is_stable())
return NoChange();
1486 if (!IsFastElementsKind(map->elements_kind()))
return NoChange();
1487 prototype_maps.push_back(map);
1494 for (Handle<Map> prototype_map : prototype_maps) {
1495 dependencies()->DependOnStableMap(MapRef(broker(), prototype_map));
1500 PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
1501 receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);
1504 if (access_infos.size() == 1) {
1505 ElementAccessInfo access_info = access_infos.front();
1508 for (
auto transition : access_info.transitions()) {
1509 Handle<Map>
const transition_source = transition.first;
1510 Handle<Map>
const transition_target = transition.second;
1511 effect = graph()->NewNode(
1512 simplified()->TransitionElementsKind(ElementsTransition(
1513 IsSimpleMapChangeTransition(transition_source->elements_kind(),
1514 transition_target->elements_kind())
1515 ? ElementsTransition::kFastTransition
1516 : ElementsTransition::kSlowTransition,
1517 transition_source, transition_target)),
1518 receiver, effect, control);
1526 effect = graph()->NewNode(common()->Checkpoint(), frame_state, effect,
1530 access_builder.BuildCheckMaps(receiver, &effect, control,
1531 access_info.receiver_maps());
1534 ValueEffectControl continuation =
1535 BuildElementAccess(receiver, index, value, effect, control,
1536 access_info, access_mode, load_mode, store_mode);
1537 value = continuation.value();
1538 effect = continuation.effect();
1539 control = continuation.control();
1543 ZoneVector<Node*> values(zone());
1544 ZoneVector<Node*> effects(zone());
1545 ZoneVector<Node*> controls(zone());
1548 Node* fallthrough_control = control;
1549 for (
size_t j = 0; j < access_infos.size(); ++j) {
1550 ElementAccessInfo
const& access_info = access_infos[j];
1551 Node* this_receiver = receiver;
1552 Node* this_value = value;
1553 Node* this_index = index;
1554 Node* this_effect = effect;
1555 Node* this_control = fallthrough_control;
1558 for (
auto transition : access_info.transitions()) {
1559 Handle<Map>
const transition_source = transition.first;
1560 Handle<Map>
const transition_target = transition.second;
1561 this_effect = graph()->NewNode(
1562 simplified()->TransitionElementsKind(
1563 ElementsTransition(IsSimpleMapChangeTransition(
1564 transition_source->elements_kind(),
1565 transition_target->elements_kind())
1566 ? ElementsTransition::kFastTransition
1567 : ElementsTransition::kSlowTransition,
1568 transition_source, transition_target)),
1569 receiver, this_effect, this_control);
1573 MapHandles
const& receiver_maps = access_info.receiver_maps();
1574 if (j == access_infos.size() - 1) {
1577 access_builder.BuildCheckMaps(receiver, &this_effect, this_control,
1579 fallthrough_control =
nullptr;
1582 ZoneHandleSet<Map> maps;
1583 for (Handle<Map> map : receiver_maps) {
1584 maps.insert(map, graph()->zone());
1586 Node* check = this_effect =
1587 graph()->NewNode(simplified()->CompareMaps(maps), receiver,
1588 this_effect, fallthrough_control);
1590 graph()->NewNode(common()->Branch(), check, fallthrough_control);
1591 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
1592 this_control = graph()->NewNode(common()->IfTrue(), branch);
1595 this_effect = graph()->NewNode(simplified()->MapGuard(maps), receiver,
1596 this_effect, this_control);
1600 ValueEffectControl continuation = BuildElementAccess(
1601 this_receiver, this_index, this_value, this_effect, this_control,
1602 access_info, access_mode, load_mode, store_mode);
1603 values.push_back(continuation.value());
1604 effects.push_back(continuation.effect());
1605 controls.push_back(continuation.control());
1608 DCHECK_NULL(fallthrough_control);
1611 int const control_count =
static_cast<int>(controls.size());
1612 if (control_count == 0) {
1613 value = effect = control = jsgraph()->Dead();
1614 }
else if (control_count == 1) {
1615 value = values.front();
1616 effect = effects.front();
1617 control = controls.front();
1619 control = graph()->NewNode(common()->Merge(control_count),
1620 control_count, &controls.front());
1621 values.push_back(control);
1622 value = graph()->NewNode(
1623 common()->Phi(MachineRepresentation::kTagged, control_count),
1624 control_count + 1, &values.front());
1625 effects.push_back(control);
1626 effect = graph()->NewNode(common()->EffectPhi(control_count),
1627 control_count + 1, &effects.front());
1632 ReplaceWithValue(node, value, effect, control);
1633 return Replace(value);
1636 Reduction JSNativeContextSpecialization::ReduceKeyedAccess(
1637 Node* node, Node* index, Node* value, FeedbackNexus
const& nexus,
1638 AccessMode access_mode, KeyedAccessLoadMode load_mode,
1639 KeyedAccessStoreMode store_mode) {
1640 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
1641 node->opcode() == IrOpcode::kJSStoreProperty);
1642 Node* receiver = NodeProperties::GetValueInput(node, 0);
1643 Node* effect = NodeProperties::GetEffectInput(node);
1644 Node* control = NodeProperties::GetControlInput(node);
1647 if (access_mode == AccessMode::kLoad) {
1648 HeapObjectMatcher mreceiver(receiver);
1649 if (mreceiver.HasValue() && !mreceiver.Value()->IsTheHole(isolate()) &&
1650 !mreceiver.Value()->IsNullOrUndefined(isolate())) {
1654 NumberMatcher mindex(index);
1655 if (mindex.IsInteger() && mindex.IsInRange(0.0, kMaxUInt32 - 1.0)) {
1656 LookupIterator it(isolate(), mreceiver.Value(),
1657 static_cast<uint32_t>(mindex.Value()),
1658 LookupIterator::OWN);
1659 if (it.state() == LookupIterator::DATA) {
1660 if (it.IsReadOnly() && !it.IsConfigurable()) {
1664 value = jsgraph()->Constant(it.GetDataValue());
1665 ReplaceWithValue(node, value, effect, control);
1666 return Replace(value);
1679 if (mreceiver.Value()->IsJSArray()) {
1680 Handle<JSArray> array = Handle<JSArray>::cast(mreceiver.Value());
1681 if (array->elements()->IsCowArray()) {
1682 Node* elements = effect = graph()->NewNode(
1683 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
1684 receiver, effect, control);
1685 Handle<FixedArray> array_elements(
1686 FixedArray::cast(array->elements()), isolate());
1688 graph()->NewNode(simplified()->ReferenceEqual(), elements,
1689 jsgraph()->HeapConstant(array_elements));
1690 effect = graph()->NewNode(
1691 simplified()->CheckIf(
1692 DeoptimizeReason::kCowArrayElementsChanged),
1693 check, effect, control);
1694 value = jsgraph()->Constant(it.GetDataValue());
1695 ReplaceWithValue(node, value, effect, control);
1696 return Replace(value);
1704 if (mreceiver.Value()->IsString()) {
1705 Handle<String>
string = Handle<String>::cast(mreceiver.Value());
1710 if (nexus.ic_state() != MEGAMORPHIC && nexus.GetKeyType() == ELEMENT) {
1712 Node* length = jsgraph()->Constant(string->length());
1716 value = BuildIndexedStringLoad(receiver, index, length, &effect,
1717 &control, load_mode);
1718 ReplaceWithValue(node, value, effect, control);
1719 return Replace(value);
1726 MapHandles receiver_maps;
1727 if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
1729 }
else if (receiver_maps.empty()) {
1730 if (flags() & kBailoutOnUninitialized) {
1731 return ReduceSoftDeoptimize(
1733 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
1737 DCHECK(!nexus.IsUninitialized());
1740 HeapObjectMatcher mindex(index);
1741 if (mindex.HasValue() && mindex.Value()->IsPrimitive()) {
1747 if (Object::ToName(isolate(), mindex.Value()).ToHandle(&name)) {
1749 if (name->AsArrayIndex(&array_index)) {
1751 index = jsgraph()->Constant(static_cast<double>(array_index));
1753 name = factory()->InternalizeName(name);
1754 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode);
1760 Name name = nexus.FindFirstName();
1761 if (!name.is_null()) {
1762 return ReduceNamedAccess(node, value, receiver_maps,
1763 handle(name, isolate()), access_mode, index);
1764 }
else if (nexus.GetKeyType() != ELEMENT) {
1769 }
else if (nexus.ic_state() == MEGAMORPHIC) {
1778 return ReduceElementAccess(node, index, value, receiver_maps, access_mode,
1779 load_mode, store_mode);
1782 Reduction JSNativeContextSpecialization::ReduceSoftDeoptimize(
1783 Node* node, DeoptimizeReason reason) {
1784 Node* effect = NodeProperties::GetEffectInput(node);
1785 Node* control = NodeProperties::GetControlInput(node);
1786 Node* frame_state = NodeProperties::FindFrameStateBefore(node);
1787 Node* deoptimize = graph()->NewNode(
1788 common()->Deoptimize(DeoptimizeKind::kSoft, reason, VectorSlotPair()),
1789 frame_state, effect, control);
1791 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
1792 Revisit(graph()->end());
1793 node->TrimInputCount(0);
1794 NodeProperties::ChangeOp(node, common()->Dead());
1795 return Changed(node);
1798 Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) {
1799 DCHECK_EQ(IrOpcode::kJSLoadProperty, node->opcode());
1800 PropertyAccess
const& p = PropertyAccessOf(node->op());
1801 Node* receiver = NodeProperties::GetValueInput(node, 0);
1802 Node* name = NodeProperties::GetValueInput(node, 1);
1803 Node* value = jsgraph()->Dead();
1804 Node* effect = NodeProperties::GetEffectInput(node);
1805 Node* control = NodeProperties::GetControlInput(node);
1846 if (name->opcode() == IrOpcode::kJSForInNext) {
1847 ForInMode
const mode = ForInModeOf(name->op());
1848 if (mode == ForInMode::kUseEnumCacheKeysAndIndices) {
1849 Node*
object = NodeProperties::GetValueInput(name, 0);
1850 Node* enumerator = NodeProperties::GetValueInput(name, 2);
1851 Node* index = NodeProperties::GetValueInput(name, 3);
1852 if (object->opcode() == IrOpcode::kJSToObject) {
1853 object = NodeProperties::GetValueInput(
object, 0);
1855 if (
object == receiver) {
1858 if (!NodeProperties::NoObservableSideEffectBetween(effect, name)) {
1860 Node* receiver_map = effect =
1861 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1862 receiver, effect, control);
1863 Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
1864 receiver_map, enumerator);
1865 effect = graph()->NewNode(
1866 simplified()->CheckIf(DeoptimizeReason::kWrongMap), check, effect,
1871 Node* descriptor_array = effect = graph()->NewNode(
1872 simplified()->LoadField(AccessBuilder::ForMapDescriptors()),
1873 enumerator, effect, control);
1874 Node* enum_cache = effect =
1875 graph()->NewNode(simplified()->LoadField(
1876 AccessBuilder::ForDescriptorArrayEnumCache()),
1877 descriptor_array, effect, control);
1878 Node* enum_indices = effect = graph()->NewNode(
1879 simplified()->LoadField(AccessBuilder::ForEnumCacheIndices()),
1880 enum_cache, effect, control);
1883 Node* check = graph()->NewNode(
1884 simplified()->BooleanNot(),
1885 graph()->NewNode(simplified()->ReferenceEqual(), enum_indices,
1886 jsgraph()->EmptyFixedArrayConstant()));
1887 effect = graph()->NewNode(
1888 simplified()->CheckIf(DeoptimizeReason::kWrongEnumIndices), check,
1892 index = effect = graph()->NewNode(
1893 simplified()->LoadElement(
1894 AccessBuilder::ForFixedArrayElement(PACKED_SMI_ELEMENTS)),
1895 enum_indices, index, effect, control);
1898 Node* value = effect = graph()->NewNode(
1899 simplified()->LoadFieldByIndex(), receiver, index, effect, control);
1900 ReplaceWithValue(node, value, effect, control);
1901 return Replace(value);
1907 if (!p.feedback().IsValid())
return NoChange();
1908 FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
1911 KeyedAccessLoadMode load_mode = nexus.GetKeyedAccessLoadMode();
1914 return ReduceKeyedAccess(node, name, value, nexus, AccessMode::kLoad,
1915 load_mode, STANDARD_STORE);
1918 Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) {
1919 DCHECK_EQ(IrOpcode::kJSStoreProperty, node->opcode());
1920 PropertyAccess
const& p = PropertyAccessOf(node->op());
1921 Node*
const index = NodeProperties::GetValueInput(node, 1);
1922 Node*
const value = NodeProperties::GetValueInput(node, 2);
1925 if (!p.feedback().IsValid())
return NoChange();
1926 FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
1929 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode();
1932 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore,
1933 STANDARD_LOAD, store_mode);
1936 Node* JSNativeContextSpecialization::InlinePropertyGetterCall(
1937 Node* receiver, Node* context, Node* frame_state, Node** effect,
1938 Node** control, ZoneVector<Node*>* if_exceptions,
1939 PropertyAccessInfo
const& access_info) {
1940 Node* target = jsgraph()->Constant(access_info.constant());
1941 FrameStateInfo
const& frame_info = FrameStateInfoOf(frame_state->op());
1942 Handle<SharedFunctionInfo> shared_info =
1943 frame_info.shared_info().ToHandleChecked();
1946 if (access_info.constant()->IsJSFunction()) {
1947 value = *effect = *control = graph()->NewNode(
1948 jsgraph()->javascript()->Call(2, CallFrequency(), VectorSlotPair(),
1949 ConvertReceiverMode::kNotNullOrUndefined),
1950 target, receiver, context, frame_state, *effect, *control);
1952 DCHECK(access_info.constant()->IsFunctionTemplateInfo());
1953 Handle<FunctionTemplateInfo> function_template_info(
1954 Handle<FunctionTemplateInfo>::cast(access_info.constant()));
1955 DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
1957 access_info.holder().is_null()
1959 : jsgraph()->Constant(access_info.holder().ToHandleChecked());
1960 value = InlineApiCall(receiver, holder, frame_state,
nullptr, effect,
1961 control, shared_info, function_template_info);
1964 if (if_exceptions !=
nullptr) {
1966 Node*
const if_exception =
1967 graph()->NewNode(common()->IfException(), *control, *effect);
1968 Node*
const if_success = graph()->NewNode(common()->IfSuccess(), *control);
1969 if_exceptions->push_back(if_exception);
1970 *control = if_success;
1975 void JSNativeContextSpecialization::InlinePropertySetterCall(
1976 Node* receiver, Node* value, Node* context, Node* frame_state,
1977 Node** effect, Node** control, ZoneVector<Node*>* if_exceptions,
1978 PropertyAccessInfo
const& access_info) {
1979 Node* target = jsgraph()->Constant(access_info.constant());
1980 FrameStateInfo
const& frame_info = FrameStateInfoOf(frame_state->op());
1981 Handle<SharedFunctionInfo> shared_info =
1982 frame_info.shared_info().ToHandleChecked();
1984 if (access_info.constant()->IsJSFunction()) {
1985 *effect = *control = graph()->NewNode(
1986 jsgraph()->javascript()->Call(3, CallFrequency(), VectorSlotPair(),
1987 ConvertReceiverMode::kNotNullOrUndefined),
1988 target, receiver, value, context, frame_state, *effect, *control);
1990 DCHECK(access_info.constant()->IsFunctionTemplateInfo());
1991 Handle<FunctionTemplateInfo> function_template_info(
1992 Handle<FunctionTemplateInfo>::cast(access_info.constant()));
1993 DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
1995 access_info.holder().is_null()
1997 : jsgraph()->Constant(access_info.holder().ToHandleChecked());
1998 InlineApiCall(receiver, holder, frame_state, value, effect, control,
1999 shared_info, function_template_info);
2002 if (if_exceptions !=
nullptr) {
2004 Node*
const if_exception =
2005 graph()->NewNode(common()->IfException(), *control, *effect);
2006 Node*
const if_success = graph()->NewNode(common()->IfSuccess(), *control);
2007 if_exceptions->push_back(if_exception);
2008 *control = if_success;
2012 Node* JSNativeContextSpecialization::InlineApiCall(
2013 Node* receiver, Node* holder, Node* frame_state, Node* value, Node** effect,
2014 Node** control, Handle<SharedFunctionInfo> shared_info,
2015 Handle<FunctionTemplateInfo> function_template_info) {
2016 Handle<CallHandlerInfo> call_handler_info = handle(
2017 CallHandlerInfo::cast(function_template_info->call_code()), isolate());
2018 Handle<Object> call_data_object(call_handler_info->data(), isolate());
2021 int const argc = value ==
nullptr ? 0 : 1;
2023 Callable call_api_callback = CodeFactory::CallApiCallback(isolate(), argc);
2024 CallInterfaceDescriptor call_interface_descriptor =
2025 call_api_callback.descriptor();
2026 auto call_descriptor = Linkage::GetStubCallDescriptor(
2027 graph()->zone(), call_interface_descriptor,
2028 call_interface_descriptor.GetStackParameterCount() + argc +
2030 CallDescriptor::kNeedsFrameState);
2032 Node* data = jsgraph()->Constant(call_data_object);
2033 ApiFunction
function(v8::ToCData<Address>(call_handler_info->callback()));
2034 Node* function_reference =
2035 graph()->NewNode(common()->ExternalConstant(ExternalReference::Create(
2036 &
function, ExternalReference::DIRECT_API_CALL)));
2037 Node* code = jsgraph()->HeapConstant(call_api_callback.code());
2040 Node* context = jsgraph()->Constant(native_context());
2041 Node* inputs[10] = {code, context, data, holder, function_reference,
2043 int index = 6 + argc;
2044 inputs[index++] = frame_state;
2045 inputs[index++] = *effect;
2046 inputs[index++] = *control;
2049 if (value !=
nullptr) {
2053 return *effect = *control =
2054 graph()->NewNode(common()->Call(call_descriptor), index, inputs);
2057 JSNativeContextSpecialization::ValueEffectControl
2058 JSNativeContextSpecialization::BuildPropertyLoad(
2059 Node* receiver, Node* context, Node* frame_state, Node* effect,
2060 Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
2061 PropertyAccessInfo
const& access_info) {
2063 Handle<JSObject> holder;
2064 PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
2065 if (access_info.holder().ToHandle(&holder)) {
2066 dependencies()->DependOnStablePrototypeChains(
2067 broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
2072 if (access_info.IsNotFound()) {
2073 value = jsgraph()->UndefinedConstant();
2074 }
else if (access_info.IsDataConstant()) {
2075 DCHECK(!FLAG_track_constant_fields);
2076 value = jsgraph()->Constant(access_info.constant());
2077 }
else if (access_info.IsAccessorConstant()) {
2078 value = InlinePropertyGetterCall(receiver, context, frame_state, &effect,
2079 &control, if_exceptions, access_info);
2080 }
else if (access_info.IsModuleExport()) {
2081 Node* cell = jsgraph()->Constant(access_info.export_cell());
2083 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForCellValue()),
2084 cell, effect, control);
2085 }
else if (access_info.IsStringLength()) {
2086 value = graph()->NewNode(simplified()->StringLength(), receiver);
2088 DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
2089 value = access_builder.BuildLoadDataField(name, access_info, receiver,
2093 return ValueEffectControl(value, effect, control);
2096 JSNativeContextSpecialization::ValueEffectControl
2097 JSNativeContextSpecialization::BuildPropertyAccess(
2098 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
2099 Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
2100 PropertyAccessInfo
const& access_info, AccessMode access_mode) {
2101 switch (access_mode) {
2102 case AccessMode::kLoad:
2103 return BuildPropertyLoad(receiver, context, frame_state, effect, control,
2104 name, if_exceptions, access_info);
2105 case AccessMode::kStore:
2106 case AccessMode::kStoreInLiteral:
2107 return BuildPropertyStore(receiver, value, context, frame_state, effect,
2108 control, name, if_exceptions, access_info,
2112 return ValueEffectControl();
2115 JSNativeContextSpecialization::ValueEffectControl
2116 JSNativeContextSpecialization::BuildPropertyStore(
2117 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
2118 Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
2119 PropertyAccessInfo
const& access_info, AccessMode access_mode) {
2121 Handle<JSObject> holder;
2122 PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
2123 if (access_info.holder().ToHandle(&holder)) {
2124 DCHECK_NE(AccessMode::kStoreInLiteral, access_mode);
2125 dependencies()->DependOnStablePrototypeChains(
2126 broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
2129 DCHECK(!access_info.IsNotFound());
2132 if (access_info.IsDataConstant()) {
2133 DCHECK(!FLAG_track_constant_fields);
2134 Node* constant_value = jsgraph()->Constant(access_info.constant());
2136 graph()->NewNode(simplified()->ReferenceEqual(), value, constant_value);
2138 graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongValue),
2139 check, effect, control);
2140 value = constant_value;
2141 }
else if (access_info.IsAccessorConstant()) {
2142 InlinePropertySetterCall(receiver, value, context, frame_state, &effect,
2143 &control, if_exceptions, access_info);
2145 DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
2146 FieldIndex
const field_index = access_info.field_index();
2147 Type const field_type = access_info.field_type();
2148 MachineRepresentation
const field_representation =
2149 access_info.field_representation();
2150 Node* storage = receiver;
2151 if (!field_index.is_inobject()) {
2152 storage = effect = graph()->NewNode(
2153 simplified()->LoadField(AccessBuilder::ForJSObjectPropertiesOrHash()),
2154 storage, effect, control);
2156 FieldAccess field_access = {
2158 field_index.offset(),
2162 MachineType::TypeForRepresentation(field_representation),
2164 bool store_to_constant_field = FLAG_track_constant_fields &&
2165 (access_mode == AccessMode::kStore) &&
2166 access_info.IsDataConstantField();
2168 DCHECK(access_mode == AccessMode::kStore ||
2169 access_mode == AccessMode::kStoreInLiteral);
2170 switch (field_representation) {
2171 case MachineRepresentation::kFloat64: {
2173 graph()->NewNode(simplified()->CheckNumber(VectorSlotPair()), value,
2175 if (!field_index.is_inobject() || field_index.is_hidden_field() ||
2176 !FLAG_unbox_double_fields) {
2177 if (access_info.HasTransitionMap()) {
2179 AllocationBuilder a(jsgraph(), effect, control);
2180 a.Allocate(HeapNumber::kSize, NOT_TENURED, Type::OtherInternal());
2181 a.Store(AccessBuilder::ForMap(),
2182 factory()->mutable_heap_number_map());
2183 a.Store(AccessBuilder::ForHeapNumberValue(), value);
2184 value = effect = a.Finish();
2186 field_access.type = Type::Any();
2187 field_access.machine_type = MachineType::TaggedPointer();
2188 field_access.write_barrier_kind = kPointerWriteBarrier;
2191 FieldAccess
const storage_access = {kTaggedBase,
2192 field_index.offset(),
2195 Type::OtherInternal(),
2196 MachineType::TaggedPointer(),
2197 kPointerWriteBarrier};
2199 graph()->NewNode(simplified()->LoadField(storage_access),
2200 storage, effect, control);
2201 field_access.offset = HeapNumber::kValueOffset;
2202 field_access.name = MaybeHandle<Name>();
2203 field_access.machine_type = MachineType::Float64();
2206 if (store_to_constant_field) {
2207 DCHECK(!access_info.HasTransitionMap());
2210 Node* current_value = effect = graph()->NewNode(
2211 simplified()->LoadField(field_access), storage, effect, control);
2213 Node* check = graph()->NewNode(simplified()->NumberEqual(),
2214 current_value, value);
2215 effect = graph()->NewNode(
2216 simplified()->CheckIf(DeoptimizeReason::kWrongValue), check,
2218 return ValueEffectControl(value, effect, control);
2222 case MachineRepresentation::kTaggedSigned:
2223 case MachineRepresentation::kTaggedPointer:
2224 case MachineRepresentation::kTagged:
2225 if (store_to_constant_field) {
2226 DCHECK(!access_info.HasTransitionMap());
2229 Node* current_value = effect = graph()->NewNode(
2230 simplified()->LoadField(field_access), storage, effect, control);
2232 Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
2233 current_value, value);
2234 effect = graph()->NewNode(
2235 simplified()->CheckIf(DeoptimizeReason::kWrongValue), check,
2237 return ValueEffectControl(value, effect, control);
2240 if (field_representation == MachineRepresentation::kTaggedSigned) {
2241 value = effect = graph()->NewNode(
2242 simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
2243 field_access.write_barrier_kind = kNoWriteBarrier;
2245 }
else if (field_representation ==
2246 MachineRepresentation::kTaggedPointer) {
2248 value = access_builder.BuildCheckHeapObject(value, &effect, control);
2249 Handle<Map> field_map;
2250 if (access_info.field_map().ToHandle(&field_map)) {
2252 effect = graph()->NewNode(
2253 simplified()->CheckMaps(CheckMapsFlag::kNone,
2254 ZoneHandleSet<Map>(field_map)),
2255 value, effect, control);
2257 field_access.write_barrier_kind = kPointerWriteBarrier;
2260 DCHECK_EQ(MachineRepresentation::kTagged, field_representation);
2263 case MachineRepresentation::kNone:
2264 case MachineRepresentation::kBit:
2265 case MachineRepresentation::kWord8:
2266 case MachineRepresentation::kWord16:
2267 case MachineRepresentation::kWord32:
2268 case MachineRepresentation::kWord64:
2269 case MachineRepresentation::kFloat32:
2270 case MachineRepresentation::kSimd128:
2275 Handle<Map> transition_map;
2276 if (access_info.transition_map().ToHandle(&transition_map)) {
2279 Handle<Map> original_map(Map::cast(transition_map->GetBackPointer()),
2281 if (original_map->UnusedPropertyFields() == 0) {
2282 DCHECK(!field_index.is_inobject());
2285 storage = effect = BuildExtendPropertiesBackingStore(
2286 original_map, storage, effect, control);
2289 effect = graph()->NewNode(simplified()->StoreField(field_access),
2290 storage, value, effect, control);
2293 field_access = AccessBuilder::ForJSObjectPropertiesOrHash();
2297 effect = graph()->NewNode(
2298 common()->BeginRegion(RegionObservability::kObservable), effect);
2299 effect = graph()->NewNode(
2300 simplified()->StoreField(AccessBuilder::ForMap()), receiver,
2301 jsgraph()->Constant(transition_map), effect, control);
2302 effect = graph()->NewNode(simplified()->StoreField(field_access), storage,
2303 value, effect, control);
2304 effect = graph()->NewNode(common()->FinishRegion(),
2305 jsgraph()->UndefinedConstant(), effect);
2308 effect = graph()->NewNode(simplified()->StoreField(field_access), storage,
2309 value, effect, control);
2313 return ValueEffectControl(value, effect, control);
2316 Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral(
2318 DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode());
2320 FeedbackParameter
const& p = FeedbackParameterOf(node->op());
2322 if (!p.feedback().IsValid())
return NoChange();
2324 FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
2325 if (nexus.IsUninitialized()) {
2329 if (nexus.ic_state() == MEGAMORPHIC) {
2333 DCHECK_EQ(MONOMORPHIC, nexus.ic_state());
2335 Map map = nexus.FindFirstMap();
2336 if (map.is_null()) {
2341 Handle<Map> receiver_map(map, isolate());
2342 if (!Map::TryUpdate(isolate(), receiver_map).ToHandle(&receiver_map))
2345 Handle<Name> cached_name =
2346 handle(Name::cast(nexus.GetFeedbackExtra()->GetHeapObjectAssumeStrong()),
2349 PropertyAccessInfo access_info;
2350 AccessInfoFactory access_info_factory(
2351 broker(), dependencies(), native_context().
object(), graph()->zone());
2352 if (!access_info_factory.ComputePropertyAccessInfo(
2353 receiver_map, cached_name, AccessMode::kStoreInLiteral,
2358 Node* receiver = NodeProperties::GetValueInput(node, 0);
2359 Node* effect = NodeProperties::GetEffectInput(node);
2360 Node* control = NodeProperties::GetControlInput(node);
2363 PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
2364 receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);
2365 access_builder.BuildCheckMaps(receiver, &effect, control,
2366 access_info.receiver_maps());
2369 Node* name = NodeProperties::GetValueInput(node, 1);
2370 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), name,
2371 jsgraph()->HeapConstant(cached_name));
2372 effect = graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongName),
2373 check, effect, control);
2375 Node* value = NodeProperties::GetValueInput(node, 2);
2376 Node* context = NodeProperties::GetContextInput(node);
2377 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node);
2380 ValueEffectControl continuation = BuildPropertyAccess(
2381 receiver, value, context, frame_state_lazy, effect, control, cached_name,
2382 nullptr, access_info, AccessMode::kStoreInLiteral);
2383 value = continuation.value();
2384 effect = continuation.effect();
2385 control = continuation.control();
2387 ReplaceWithValue(node, value, effect, control);
2388 return Replace(value);
2391 Reduction JSNativeContextSpecialization::ReduceJSStoreInArrayLiteral(
2393 DCHECK_EQ(IrOpcode::kJSStoreInArrayLiteral, node->opcode());
2394 FeedbackParameter
const& p = FeedbackParameterOf(node->op());
2395 Node*
const receiver = NodeProperties::GetValueInput(node, 0);
2396 Node*
const index = NodeProperties::GetValueInput(node, 1);
2397 Node*
const value = NodeProperties::GetValueInput(node, 2);
2398 Node*
const effect = NodeProperties::GetEffectInput(node);
2401 if (!p.feedback().IsValid())
return NoChange();
2402 FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
2405 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode();
2408 MapHandles receiver_maps;
2409 if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
2411 }
else if (receiver_maps.empty()) {
2412 if (flags() & kBailoutOnUninitialized) {
2413 return ReduceSoftDeoptimize(
2415 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
2419 DCHECK(!nexus.IsUninitialized());
2420 DCHECK_EQ(ELEMENT, nexus.GetKeyType());
2422 if (nexus.ic_state() == MEGAMORPHIC)
return NoChange();
2425 return ReduceElementAccess(node, index, value, receiver_maps,
2426 AccessMode::kStoreInLiteral, STANDARD_LOAD,
2430 Reduction JSNativeContextSpecialization::ReduceJSToObject(Node* node) {
2431 DCHECK_EQ(IrOpcode::kJSToObject, node->opcode());
2432 Node* receiver = NodeProperties::GetValueInput(node, 0);
2433 Node* effect = NodeProperties::GetEffectInput(node);
2435 ZoneHandleSet<Map> receiver_maps;
2436 NodeProperties::InferReceiverMapsResult result =
2437 NodeProperties::InferReceiverMaps(broker(), receiver, effect,
2439 if (result == NodeProperties::kNoReceiverMaps)
return NoChange();
2441 for (
size_t i = 0;
i < receiver_maps.size(); ++
i) {
2442 if (!receiver_maps[
i]->IsJSReceiverMap())
return NoChange();
2445 ReplaceWithValue(node, receiver, effect);
2446 return Replace(receiver);
2451 ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) {
2453 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \ 2454 case TYPE##_ELEMENTS: \ 2455 return kExternal##Type##Array; 2456 TYPED_ARRAYS(TYPED_ARRAY_CASE)
2457 #undef TYPED_ARRAY_CASE 2464 base::Optional<JSTypedArrayRef> GetTypedArrayConstant(JSHeapBroker* broker,
2466 HeapObjectMatcher m(receiver);
2467 if (!m.HasValue())
return base::nullopt;
2468 ObjectRef
object = m.Ref(broker);
2469 if (!
object.IsJSTypedArray())
return base::nullopt;
2470 JSTypedArrayRef typed_array =
object.AsJSTypedArray();
2471 if (typed_array.is_on_heap())
return base::nullopt;
2477 JSNativeContextSpecialization::ValueEffectControl
2478 JSNativeContextSpecialization::BuildElementAccess(
2479 Node* receiver, Node* index, Node* value, Node* effect, Node* control,
2480 ElementAccessInfo
const& access_info, AccessMode access_mode,
2481 KeyedAccessLoadMode load_mode, KeyedAccessStoreMode store_mode) {
2485 ElementsKind elements_kind = access_info.elements_kind();
2486 MapHandles
const& receiver_maps = access_info.receiver_maps();
2488 if (IsFixedTypedArrayElementsKind(elements_kind)) {
2492 Node* external_pointer;
2496 base::Optional<JSTypedArrayRef> typed_array =
2497 GetTypedArrayConstant(broker(), receiver);
2498 if (typed_array.has_value()) {
2499 typed_array->Serialize();
2500 buffer = jsgraph()->Constant(typed_array->buffer());
2502 jsgraph()->Constant(static_cast<double>(typed_array->length_value()));
2507 base_pointer = jsgraph()->ZeroConstant();
2509 jsgraph()->PointerConstant(typed_array->elements_external_pointer());
2512 length = effect = graph()->NewNode(
2513 simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()),
2514 receiver, effect, control);
2517 buffer = effect = graph()->NewNode(
2518 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
2519 receiver, effect, control);
2522 Node* elements = effect = graph()->NewNode(
2523 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
2524 receiver, effect, control);
2531 if (V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP == 0) {
2532 base_pointer = jsgraph()->ZeroConstant();
2534 base_pointer = effect = graph()->NewNode(
2535 simplified()->LoadField(
2536 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
2537 elements, effect, control);
2541 external_pointer = effect = graph()->NewNode(
2542 simplified()->LoadField(
2543 AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
2544 elements, effect, control);
2548 if (isolate()->IsArrayBufferNeuteringIntact()) {
2551 dependencies()->DependOnProtector(PropertyCellRef(
2552 broker(), factory()->array_buffer_neutering_protector()));
2556 Node* buffer_bit_field = effect = graph()->NewNode(
2557 simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
2558 buffer, effect, control);
2559 Node* check = graph()->NewNode(
2560 simplified()->NumberEqual(),
2562 simplified()->NumberBitwiseAnd(), buffer_bit_field,
2563 jsgraph()->Constant(JSArrayBuffer::WasNeuteredBit::kMask)),
2564 jsgraph()->ZeroConstant());
2565 effect = graph()->NewNode(
2566 simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasNeutered),
2567 check, effect, control);
2570 if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS ||
2571 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
2575 index = effect = graph()->NewNode(
2576 simplified()->CheckSmi(VectorSlotPair()), index, effect, control);
2581 index = graph()->NewNode(simplified()->NumberToUint32(), index);
2585 graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
2586 length, effect, control);
2590 ExternalArrayType external_array_type =
2591 GetArrayTypeFromElementsKind(elements_kind);
2592 switch (access_mode) {
2593 case AccessMode::kLoad: {
2595 if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS) {
2597 graph()->NewNode(simplified()->NumberLessThan(), index, length);
2598 Node* branch = graph()->NewNode(
2599 common()->Branch(BranchHint::kTrue,
2600 IsSafetyCheck::kCriticalSafetyCheck),
2603 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
2604 Node* etrue = effect;
2608 vtrue = etrue = graph()->NewNode(
2609 simplified()->LoadTypedElement(external_array_type), buffer,
2610 base_pointer, external_pointer, index, etrue, if_true);
2613 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
2614 Node* efalse = effect;
2618 vfalse = jsgraph()->UndefinedConstant();
2621 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2623 graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
2625 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
2626 vtrue, vfalse, control);
2629 value = effect = graph()->NewNode(
2630 simplified()->LoadTypedElement(external_array_type), buffer,
2631 base_pointer, external_pointer, index, effect, control);
2635 case AccessMode::kStoreInLiteral:
2638 case AccessMode::kStore: {
2641 value = effect = graph()->NewNode(
2642 simplified()->SpeculativeToNumber(
2643 NumberOperationHint::kNumberOrOddball, VectorSlotPair()),
2644 value, effect, control);
2650 if (external_array_type == kExternalUint8ClampedArray) {
2651 value = graph()->NewNode(simplified()->NumberToUint8Clamped(), value);
2655 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
2657 graph()->NewNode(simplified()->NumberLessThan(), index, length);
2658 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
2661 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
2662 Node* etrue = effect;
2665 etrue = graph()->NewNode(
2666 simplified()->StoreTypedElement(external_array_type), buffer,
2667 base_pointer, external_pointer, index, value, etrue, if_true);
2670 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
2671 Node* efalse = effect;
2676 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2678 graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
2681 effect = graph()->NewNode(
2682 simplified()->StoreTypedElement(external_array_type), buffer,
2683 base_pointer, external_pointer, index, value, effect, control);
2690 Node* elements = effect = graph()->NewNode(
2691 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
2696 if (access_mode == AccessMode::kStore &&
2697 IsSmiOrObjectElementsKind(elements_kind) &&
2698 !IsCOWHandlingStoreMode(store_mode)) {
2699 effect = graph()->NewNode(
2700 simplified()->CheckMaps(
2701 CheckMapsFlag::kNone,
2702 ZoneHandleSet<Map>(factory()->fixed_array_map())),
2703 elements, effect, control);
2707 bool receiver_is_jsarray = HasOnlyJSArrayMaps(broker(), receiver_maps);
2710 Node* length = effect =
2713 simplified()->LoadField(
2714 AccessBuilder::ForJSArrayLength(elements_kind)),
2715 receiver, effect, control)
2717 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
2718 elements, effect, control);
2721 if (IsGrowStoreMode(store_mode)) {
2723 DCHECK(access_mode == AccessMode::kStore ||
2724 access_mode == AccessMode::kStoreInLiteral);
2725 }
else if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS &&
2726 CanTreatHoleAsUndefined(receiver_maps)) {
2730 index = effect = graph()->NewNode(
2731 simplified()->CheckBounds(VectorSlotPair()), index,
2732 jsgraph()->Constant(Smi::kMaxValue), effect, control);
2736 graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
2737 length, effect, control);
2741 Type element_type = Type::NonInternal();
2742 MachineType element_machine_type = MachineType::AnyTagged();
2743 if (IsDoubleElementsKind(elements_kind)) {
2744 element_type = Type::Number();
2745 element_machine_type = MachineType::Float64();
2746 }
else if (IsSmiElementsKind(elements_kind)) {
2747 element_type = Type::SignedSmall();
2748 element_machine_type = MachineType::TaggedSigned();
2750 ElementAccess element_access = {
2751 kTaggedBase, FixedArray::kHeaderSize,
2752 element_type, element_machine_type,
2753 kFullWriteBarrier, LoadSensitivity::kCritical};
2756 if (access_mode == AccessMode::kLoad) {
2759 if (IsHoleyElementsKind(elements_kind)) {
2760 element_access.type =
2761 Type::Union(element_type, Type::Hole(), graph()->zone());
2763 if (elements_kind == HOLEY_ELEMENTS ||
2764 elements_kind == HOLEY_SMI_ELEMENTS) {
2765 element_access.machine_type = MachineType::AnyTagged();
2769 if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS &&
2770 CanTreatHoleAsUndefined(receiver_maps)) {
2772 graph()->NewNode(simplified()->NumberLessThan(), index, length);
2773 Node* branch = graph()->NewNode(
2774 common()->Branch(BranchHint::kTrue,
2775 IsSafetyCheck::kCriticalSafetyCheck),
2778 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
2779 Node* etrue = effect;
2784 graph()->NewNode(simplified()->LoadElement(element_access),
2785 elements, index, etrue, if_true);
2790 if (elements_kind == HOLEY_ELEMENTS ||
2791 elements_kind == HOLEY_SMI_ELEMENTS) {
2793 vtrue = graph()->NewNode(
2794 simplified()->ConvertTaggedHoleToUndefined(), vtrue);
2795 }
else if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
2798 vtrue = etrue = graph()->NewNode(
2799 simplified()->CheckFloat64Hole(
2800 CheckFloat64HoleMode::kAllowReturnHole, VectorSlotPair()),
2801 vtrue, etrue, if_true);
2805 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
2806 Node* efalse = effect;
2810 vfalse = jsgraph()->UndefinedConstant();
2813 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2815 graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
2817 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
2818 vtrue, vfalse, control);
2822 graph()->NewNode(simplified()->LoadElement(element_access),
2823 elements, index, effect, control);
2827 if (elements_kind == HOLEY_ELEMENTS ||
2828 elements_kind == HOLEY_SMI_ELEMENTS) {
2830 if (CanTreatHoleAsUndefined(receiver_maps)) {
2832 value = graph()->NewNode(
2833 simplified()->ConvertTaggedHoleToUndefined(), value);
2836 value = effect = graph()->NewNode(
2837 simplified()->CheckNotTaggedHole(), value, effect, control);
2839 }
else if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
2841 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole;
2843 if (CanTreatHoleAsUndefined(receiver_maps)) {
2846 mode = CheckFloat64HoleMode::kAllowReturnHole;
2848 value = effect = graph()->NewNode(
2849 simplified()->CheckFloat64Hole(mode, VectorSlotPair()), value,
2854 DCHECK(access_mode == AccessMode::kStore ||
2855 access_mode == AccessMode::kStoreInLiteral);
2856 if (IsSmiElementsKind(elements_kind)) {
2857 value = effect = graph()->NewNode(
2858 simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
2859 }
else if (IsDoubleElementsKind(elements_kind)) {
2861 graph()->NewNode(simplified()->CheckNumber(VectorSlotPair()), value,
2864 value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
2868 if (IsSmiOrObjectElementsKind(elements_kind) &&
2869 store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
2871 graph()->NewNode(simplified()->EnsureWritableFastElements(),
2872 receiver, elements, effect, control);
2873 }
else if (IsGrowStoreMode(store_mode)) {
2875 Node* elements_length = effect = graph()->NewNode(
2876 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
2877 elements, effect, control);
2890 IsHoleyElementsKind(elements_kind)
2891 ? graph()->NewNode(simplified()->NumberAdd(), elements_length,
2892 jsgraph()->Constant(JSObject::kMaxGap))
2893 : graph()->NewNode(simplified()->NumberAdd(), length,
2894 jsgraph()->OneConstant());
2896 graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
2897 limit, effect, control);
2900 GrowFastElementsMode mode =
2901 IsDoubleElementsKind(elements_kind)
2902 ? GrowFastElementsMode::kDoubleElements
2903 : GrowFastElementsMode::kSmiOrObjectElements;
2904 elements = effect = graph()->NewNode(
2905 simplified()->MaybeGrowFastElements(mode, VectorSlotPair()),
2906 receiver, elements, index, elements_length, effect, control);
2910 if (IsSmiOrObjectElementsKind(elements_kind) &&
2911 store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW) {
2913 graph()->NewNode(simplified()->EnsureWritableFastElements(),
2914 receiver, elements, effect, control);
2918 if (receiver_is_jsarray) {
2920 graph()->NewNode(simplified()->NumberLessThan(), index, length);
2921 Node* branch = graph()->NewNode(common()->Branch(), check, control);
2923 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
2924 Node* etrue = effect;
2930 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
2931 Node* efalse = effect;
2935 Node* new_length = graph()->NewNode(
2936 simplified()->NumberAdd(), index, jsgraph()->OneConstant());
2937 efalse = graph()->NewNode(
2938 simplified()->StoreField(
2939 AccessBuilder::ForJSArrayLength(elements_kind)),
2940 receiver, new_length, efalse, if_false);
2943 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2945 graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
2950 effect = graph()->NewNode(simplified()->StoreElement(element_access),
2951 elements, index, value, effect, control);
2955 return ValueEffectControl(value, effect, control);
2958 Node* JSNativeContextSpecialization::BuildIndexedStringLoad(
2959 Node* receiver, Node* index, Node* length, Node** effect, Node** control,
2960 KeyedAccessLoadMode load_mode) {
2961 if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS &&
2962 isolate()->IsNoElementsProtectorIntact()) {
2963 dependencies()->DependOnProtector(
2964 PropertyCellRef(broker(), factory()->no_elements_protector()));
2967 index = *effect = graph()->NewNode(
2968 simplified()->CheckBounds(VectorSlotPair()), index,
2969 jsgraph()->Constant(String::kMaxLength), *effect, *control);
2974 graph()->NewNode(simplified()->NumberLessThan(), index, length);
2976 graph()->NewNode(common()->Branch(BranchHint::kTrue,
2977 IsSafetyCheck::kCriticalSafetyCheck),
2980 Node* masked_index = graph()->NewNode(simplified()->PoisonIndex(), index);
2982 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
2984 Node* vtrue = etrue =
2985 graph()->NewNode(simplified()->StringCharCodeAt(), receiver,
2986 masked_index, *effect, if_true);
2987 vtrue = graph()->NewNode(simplified()->StringFromSingleCharCode(), vtrue);
2989 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
2990 Node* vfalse = jsgraph()->UndefinedConstant();
2992 *control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2994 graph()->NewNode(common()->EffectPhi(2), etrue, *effect, *control);
2995 return graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
2996 vtrue, vfalse, *control);
3000 graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
3001 length, *effect, *control);
3003 Node* masked_index = graph()->NewNode(simplified()->PoisonIndex(), index);
3006 Node* value = *effect =
3007 graph()->NewNode(simplified()->StringCharCodeAt(), receiver,
3008 masked_index, *effect, *control);
3009 value = graph()->NewNode(simplified()->StringFromSingleCharCode(), value);
3014 Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore(
3015 Handle<Map> map, Node* properties, Node* effect, Node* control) {
3025 DCHECK_EQ(0, map->UnusedPropertyFields());
3027 int length = map->NextFreePropertyIndex() - map->GetInObjectProperties();
3028 int new_length = length + JSObject::kFieldsAdded;
3030 ZoneVector<Node*> values(zone());
3031 values.reserve(new_length);
3032 for (
int i = 0;
i < length; ++
i) {
3033 Node* value = effect = graph()->NewNode(
3034 simplified()->LoadField(AccessBuilder::ForFixedArraySlot(
i)),
3035 properties, effect, control);
3036 values.push_back(value);
3039 for (
int i = 0;
i < JSObject::kFieldsAdded; ++
i) {
3040 values.push_back(jsgraph()->UndefinedConstant());
3046 hash = graph()->NewNode(
3047 common()->Select(MachineRepresentation::kTaggedSigned),
3048 graph()->NewNode(simplified()->ObjectIsSmi(), properties), properties,
3049 jsgraph()->SmiConstant(PropertyArray::kNoHashSentinel));
3050 hash = effect = graph()->NewNode(common()->TypeGuard(Type::SignedSmall()),
3051 hash, effect, control);
3053 graph()->NewNode(simplified()->NumberShiftLeft(), hash,
3054 jsgraph()->Constant(PropertyArray::HashField::kShift));
3056 hash = effect = graph()->NewNode(
3057 simplified()->LoadField(AccessBuilder::ForPropertyArrayLengthAndHash()),
3058 properties, effect, control);
3060 graph()->NewNode(simplified()->NumberBitwiseAnd(), hash,
3061 jsgraph()->Constant(PropertyArray::HashField::kMask));
3063 Node* new_length_and_hash = graph()->NewNode(
3064 simplified()->NumberBitwiseOr(), jsgraph()->Constant(new_length), hash);
3066 new_length_and_hash = effect =
3067 graph()->NewNode(common()->TypeGuard(Type::SignedSmall()),
3068 new_length_and_hash, effect, control);
3071 AllocationBuilder a(jsgraph(), effect, control);
3072 a.Allocate(PropertyArray::SizeFor(new_length), NOT_TENURED,
3073 Type::OtherInternal());
3074 a.Store(AccessBuilder::ForMap(), jsgraph()->PropertyArrayMapConstant());
3075 a.Store(AccessBuilder::ForPropertyArrayLengthAndHash(), new_length_and_hash);
3076 for (
int i = 0;
i < new_length; ++
i) {
3077 a.Store(AccessBuilder::ForFixedArraySlot(
i), values[
i]);
3082 Node* JSNativeContextSpecialization::BuildCheckEqualsName(Handle<Name> name,
3086 DCHECK(name->IsUniqueName());
3087 Operator
const*
const op =
3088 name->IsSymbol() ? simplified()->CheckEqualsSymbol()
3089 : simplified()->CheckEqualsInternalizedString();
3090 return graph()->NewNode(op, jsgraph()->HeapConstant(name), value, effect,
3094 bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
3095 MapHandles
const& receiver_maps) {
3099 for (Handle<Map> map : receiver_maps) {
3100 MapRef receiver_map(broker(), map);
3103 receiver_map.SerializePrototype();
3104 ObjectRef receiver_prototype = receiver_map.prototype();
3105 if (!receiver_prototype.IsJSObject() ||
3106 !broker()->IsArrayOrObjectPrototype(receiver_prototype.AsJSObject())) {
3112 if (!isolate()->IsNoElementsProtectorIntact())
return false;
3114 dependencies()->DependOnProtector(
3115 PropertyCellRef(broker(), factory()->no_elements_protector()));
3119 bool JSNativeContextSpecialization::ExtractReceiverMaps(
3120 Node* receiver, Node* effect, FeedbackNexus
const& nexus,
3121 MapHandles* receiver_maps) {
3122 DCHECK_EQ(0, receiver_maps->size());
3123 if (nexus.IsUninitialized())
return true;
3129 FeedbackSlotKind kind = nexus.kind();
3130 bool use_inference =
3131 !IsKeyedStoreICKind(kind) && !IsStoreInArrayLiteralICKind(kind);
3132 if (use_inference && InferReceiverMaps(receiver, effect, receiver_maps)) {
3139 if (nexus.ExtractMaps(receiver_maps) != 0) {
3141 Handle<Map> receiver_map;
3142 if (InferReceiverRootMap(receiver).ToHandle(&receiver_map)) {
3143 DCHECK(!receiver_map->is_abandoned_prototype_map());
3144 Isolate* isolate = this->isolate();
3145 receiver_maps->erase(
3146 std::remove_if(receiver_maps->begin(), receiver_maps->end(),
3147 [receiver_map, isolate](
const Handle<Map>& map) {
3148 return map->is_abandoned_prototype_map() ||
3149 map->FindRootMap(isolate) != *receiver_map;
3151 receiver_maps->end());
3159 bool JSNativeContextSpecialization::InferReceiverMaps(
3160 Node* receiver, Node* effect, MapHandles* receiver_maps) {
3161 ZoneHandleSet<Map> maps;
3162 NodeProperties::InferReceiverMapsResult result =
3163 NodeProperties::InferReceiverMaps(broker(), receiver, effect, &maps);
3164 if (result == NodeProperties::kReliableReceiverMaps) {
3165 for (
size_t i = 0;
i < maps.size(); ++
i) {
3166 receiver_maps->push_back(maps[
i]);
3169 }
else if (result == NodeProperties::kUnreliableReceiverMaps) {
3172 for (
size_t i = 0;
i < maps.size(); ++
i) {
3173 MapRef map(broker(), maps[
i]);
3174 if (!map.is_stable())
return false;
3176 for (
size_t i = 0;
i < maps.size(); ++
i) {
3177 receiver_maps->push_back(maps[
i]);
3184 MaybeHandle<Map> JSNativeContextSpecialization::InferReceiverRootMap(
3186 HeapObjectMatcher m(receiver);
3188 return handle(m.Value()->map()->FindRootMap(isolate()), isolate());
3189 }
else if (m.IsJSCreate()) {
3190 HeapObjectMatcher mtarget(m.InputAt(0));
3191 HeapObjectMatcher mnewtarget(m.InputAt(1));
3192 if (mtarget.HasValue() && mnewtarget.HasValue()) {
3193 Handle<JSFunction> constructor =
3194 Handle<JSFunction>::cast(mtarget.Value());
3195 if (constructor->has_initial_map()) {
3196 Handle<Map> initial_map(constructor->initial_map(), isolate());
3197 if (initial_map->constructor_or_backpointer() == *mnewtarget.Value()) {
3198 DCHECK_EQ(*initial_map, initial_map->FindRootMap(isolate()));
3204 return MaybeHandle<Map>();
3207 Graph* JSNativeContextSpecialization::graph()
const {
3208 return jsgraph()->graph();
3211 Isolate* JSNativeContextSpecialization::isolate()
const {
3212 return jsgraph()->isolate();
3215 Factory* JSNativeContextSpecialization::factory()
const {
3216 return isolate()->factory();
3219 CommonOperatorBuilder* JSNativeContextSpecialization::common()
const {
3220 return jsgraph()->common();
3223 JSOperatorBuilder* JSNativeContextSpecialization::javascript()
const {
3224 return jsgraph()->javascript();
3227 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified()
const {
3228 return jsgraph()->simplified();
3231 #undef V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP