v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
ast.cc
Go to the documentation of this file.
1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/ast/ast.h"
6
7#include <cmath> // For isfinite.
8#include <vector>
9
11#include "src/ast/scopes.h"
12#include "src/base/hashmap.h"
13#include "src/base/logging.h"
26#include "src/objects/map.h"
32
33namespace v8 {
34namespace internal {
35
36// ----------------------------------------------------------------------------
37// Implementation of other node functionality.
38
39#ifdef DEBUG
40
41void AstNode::Print(Isolate* isolate) { AstPrinter::PrintOut(isolate, this); }
42
43#endif // DEBUG
44
45#define RETURN_NODE(Node) \
46 case k##Node: \
47 return static_cast<Node*>(this);
48
50 switch (node_type()) {
52 default:
53 return nullptr;
54 }
55}
56
58 switch (node_type()) {
60 default:
61 return nullptr;
62 }
63}
64
65#undef RETURN_NODE
66
68 return IsLiteral() && AsLiteral()->type() == Literal::kSmi;
69}
70
72 return IsLiteral() && AsLiteral()->IsNumber();
73}
74
76 return IsLiteral() && AsLiteral()->type() == Literal::kString;
77}
78
80 return IsLiteral() && AsLiteral()->type() == Literal::kConsString;
81}
82
84 return IsLiteral() && AsLiteral()->IsPropertyName();
85}
86
88 return IsLiteral() && AsLiteral()->type() == Literal::kNull;
89}
90
92 return IsLiteral() && AsLiteral()->type() == Literal::kBoolean;
93}
94
96 return IsLiteral() && AsLiteral()->type() == Literal::kTheHole;
97}
98
100 if (IsLiteral()) return true;
102 if (literal == nullptr) return false;
103 return literal->IsSimple();
104}
105
107 if (IsLiteral() && AsLiteral()->type() == Literal::kUndefined) return true;
108
109 const VariableProxy* var_proxy = AsVariableProxy();
110 if (var_proxy == nullptr) return false;
111 Variable* var = var_proxy->var();
112 // The global identifier "undefined" is immutable. Everything
113 // else could be reassigned.
114 return var != nullptr && var->IsUnallocated() &&
115 var_proxy->raw_name()->IsOneByteEqualTo("undefined");
116}
117
119 return IsLiteral() && !IsNullOrUndefinedLiteral();
120}
121
123 return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
124}
125
127 return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
128}
129
131 return IsVariableProxy() && AsVariableProxy()->IsPrivateName();
132}
133
135 return IsProperty() ||
136 (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
137}
138
140 return (IsFunctionLiteral() &&
141 AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
142 (IsClassLiteral() &&
143 AsClassLiteral()->IsAnonymousFunctionDefinition());
144}
145
147 return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
148}
149
151 return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
152}
153
154VariableProxy::VariableProxy(Variable* var, int start_position)
155 : Expression(start_position, kVariableProxy),
156 raw_name_(var->raw_name()),
157 next_unresolved_(nullptr) {
158 DCHECK(!var->is_this());
162 BindTo(var);
163}
164
166 : Expression(copy_from->position(), kVariableProxy),
167 next_unresolved_(nullptr) {
168 bit_field_ = copy_from->bit_field_;
169 DCHECK(!copy_from->is_resolved());
170 raw_name_ = copy_from->raw_name_;
171}
172
180
182 Expression* value, int pos)
183 : Expression(pos, node_type), target_(target), value_(value) {
185}
186
193
195 if (raw_inferred_name_ != nullptr) {
196 return raw_inferred_name_->GetString(isolate);
197 }
198 DCHECK(!shared_function_info_.is_null());
199 return handle(shared_function_info_->inferred_name(), isolate);
200}
201
208
212
216
220
222 return scope()->start_position();
223}
224
226
230
232
233std::unique_ptr<char[]> FunctionLiteral::GetDebugName() const {
234 const AstConsString* cons_string;
235 if (raw_name_ != nullptr && !raw_name_->IsEmpty()) {
236 cons_string = raw_name_;
237 } else if (raw_inferred_name_ != nullptr && !raw_inferred_name_->IsEmpty()) {
238 cons_string = raw_inferred_name_;
239 } else if (!shared_function_info_.is_null()) {
240 return shared_function_info_->inferred_name()->ToCString();
241 } else {
242 char* empty_str = new char[1];
243 empty_str[0] = 0;
244 return std::unique_ptr<char[]>(empty_str);
245 }
246
247 // TODO(rmcilroy): Deal with two-character strings.
248 std::vector<char> result_vec;
249 std::forward_list<const AstRawString*> strings = cons_string->ToRawStrings();
250 for (const AstRawString* string : strings) {
251 if (!string->is_one_byte()) break;
252 for (int i = 0; i < string->length(); i++) {
253 result_vec.push_back(string->raw_data()[i]);
254 }
255 }
256 std::unique_ptr<char[]> result(new char[result_vec.size() + 1]);
257 if (result_vec.size()) {
258 memcpy(result.get(), result_vec.data(), result_vec.size());
259 }
260 result[result_vec.size()] = '\0';
261 return result;
262}
263
267
271
275
277 Kind kind, bool is_computed_name)
278 : LiteralProperty(key, value, is_computed_name),
279 kind_(kind),
280 emit_store_(true) {}
281
283 Expression* key, Expression* value,
284 bool is_computed_name)
285 : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
286 if (!is_computed_name && key->AsLiteral()->IsRawString() &&
287 key->AsLiteral()->AsRawString() == ast_value_factory->proto_string()) {
288 kind_ = PROTOTYPE;
289 } else if (value_->AsMaterializedLiteral() != nullptr) {
290 kind_ = MATERIALIZED_LITERAL;
291 } else if (value_->IsLiteral()) {
292 kind_ = CONSTANT;
293 } else {
294 kind_ = COMPUTED;
295 }
296}
297
303
305 Kind kind, bool is_static,
306 bool is_computed_name,
307 bool is_private)
308 : LiteralProperty(key, value, is_computed_name),
309 kind_(kind),
310 is_static_(is_static),
311 is_private_(is_private),
312 private_or_computed_name_proxy_(nullptr) {}
313
315 AutoAccessorInfo* info,
316 bool is_static,
317 bool is_computed_name,
318 bool is_private)
319 : LiteralProperty(key, value, is_computed_name),
320 kind_(Kind::AUTO_ACCESSOR),
321 is_static_(is_static),
322 is_private_(is_private),
323 auto_accessor_info_(info) {
324 DCHECK_NOT_NULL(info);
325}
326
331
335
337
341
345 for (int i = properties()->length() - 1; i >= 0; i--) {
346 ObjectLiteral::Property* property = properties()->at(i);
347 if (property->is_computed_name()) continue;
348 if (property->IsPrototype()) continue;
349 Literal* literal = property->key()->AsLiteral();
350 DCHECK(!literal->IsNullLiteral());
351
352 uint32_t hash = literal->Hash();
353 ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash);
354 if (entry->value == nullptr) {
355 entry->value = property;
356 } else {
357 // We already have a later definition of this property, so we don't need
358 // to emit a store for the current one.
359 //
360 // There are two subtleties here.
361 //
362 // (1) Emitting a store might actually be incorrect. For example, in {get
363 // foo() {}, foo: 42}, the getter store would override the data property
364 // (which, being a non-computed compile-time valued property, is already
365 // part of the initial literal object.
366 //
367 // (2) If the later definition is an accessor (say, a getter), and the
368 // current definition is a complementary accessor (here, a setter), then
369 // we still must emit a store for the current definition.
370
371 auto later_kind =
372 static_cast<ObjectLiteral::Property*>(entry->value)->kind();
373 bool complementary_accessors =
374 (property->kind() == GETTER && later_kind == SETTER) ||
375 (property->kind() == SETTER && later_kind == GETTER);
376 if (!complementary_accessors) {
377 property->set_emit_store(false);
378 if (later_kind == GETTER || later_kind == SETTER) {
379 entry->value = property;
380 }
381 }
382 }
383 }
384}
385
386int ObjectLiteralBoilerplateBuilder::ComputeFlags(bool disable_mementos) const {
387 int flags = LiteralBoilerplateBuilder::ComputeFlags(disable_mementos);
390 return flags;
391}
392
394 // We still check for __proto__:null after computed property names.
395 for (; i < properties()->length(); i++) {
396 if (properties()->at(i)->IsNullPrototype()) {
398 break;
399 }
400 }
401}
402
409
411 if (is_initialized()) return;
412 bool is_simple = true;
413 bool has_seen_prototype = false;
415 DepthKind depth_acc = kShallow;
416 uint32_t nof_properties = 0;
417 uint32_t elements = 0;
418 uint32_t max_element_index = 0;
419 for (int i = 0; i < properties()->length(); i++) {
420 ObjectLiteral::Property* property = properties()->at(i);
421 if (property->IsPrototype()) {
422 has_seen_prototype = true;
423 // __proto__:null has no side-effects and is set directly on the
424 // boilerplate.
425 if (property->IsNullPrototype()) {
427 continue;
428 }
430 is_simple = false;
431 continue;
432 }
433 if (nof_properties == boilerplate_properties_) {
434 DCHECK(property->is_computed_name());
435 is_simple = false;
436 if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
437 break;
438 }
439 DCHECK(!property->is_computed_name());
440
441 MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
442 if (literal != nullptr) {
444 depth_acc = kNotShallow;
445 needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
446 }
447
448 Literal* key = property->key()->AsLiteral();
449 Expression* value = property->value();
450
451 bool is_compile_time_value = value->IsCompileTimeValue();
452 is_simple = is_simple && is_compile_time_value;
453
454 // Keep track of the number of elements in the object literal and
455 // the largest element index. If the largest element index is
456 // much larger than the number of elements, creating an object
457 // literal with fast elements will be a waste of space.
458 uint32_t element_index = 0;
459 if (key->AsArrayIndex(&element_index)) {
460 max_element_index = std::max(element_index, max_element_index);
461 elements++;
462 } else {
463 DCHECK(key->IsPropertyName());
464 }
465
466 nof_properties++;
467 }
468
469 set_depth(depth_acc);
472 set_has_elements(elements > 0);
473 set_fast_elements((max_element_index <= 32) ||
474 ((2 * elements) >= max_element_index));
475}
476
477template <typename IsolateT>
479 IsolateT* isolate) {
480 if (!boilerplate_description_.is_null()) return;
481
482 int index_keys = 0;
483 bool has_seen_proto = false;
484 for (int i = 0; i < properties()->length(); i++) {
485 ObjectLiteral::Property* property = properties()->at(i);
486 if (property->IsPrototype()) {
487 has_seen_proto = true;
488 continue;
489 }
490 if (property->is_computed_name()) continue;
491
492 Literal* key = property->key()->AsLiteral();
493 if (!key->IsPropertyName()) index_keys++;
494 }
495
497 isolate->factory()->NewObjectBoilerplateDescription(
498 boilerplate_properties_, properties()->length(), index_keys,
499 has_seen_proto);
500
501 int position = 0;
502 for (int i = 0; i < properties()->length(); i++) {
503 ObjectLiteral::Property* property = properties()->at(i);
504 if (property->IsPrototype()) continue;
505
506 if (static_cast<uint32_t>(position) == boilerplate_properties_) {
507 DCHECK(property->is_computed_name());
508 break;
509 }
510 DCHECK(!property->is_computed_name());
511
512 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
513 if (m_literal != nullptr) {
514 BuildConstants(isolate, m_literal);
515 }
516
517 // Add CONSTANT and COMPUTED properties to boilerplate. Use the
518 // 'uninitialized' Oddball for COMPUTED properties, the real value is filled
519 // in at runtime. The enumeration order is maintained.
520 Literal* key_literal = property->key()->AsLiteral();
521 uint32_t element_index = 0;
523 key_literal->AsArrayIndex(&element_index)
524 ? isolate->factory()
525 ->template NewNumberFromUint<AllocationType::kOld>(
526 element_index)
527 : Cast<Object>(key_literal->AsRawPropertyName()->string());
529 GetBoilerplateValue(property->value(), isolate);
530 boilerplate_description->set_key_value(position++, *key, *value);
531 }
532
534
536}
543
545 // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
546 // literals don't support copy-on-write (COW) elements for now.
547 // TODO(mvstanton): make object literals support COW elements.
548 return fast_elements() && is_shallow() &&
551}
552
553// static
554template <typename IsolateT>
556 Expression* expression, IsolateT* isolate) {
557 if (expression->IsLiteral()) {
558 return expression->AsLiteral()->BuildValue(isolate);
559 }
560 if (expression->IsCompileTimeValue()) {
561 if (expression->IsObjectLiteral()) {
562 ObjectLiteral* object_literal = expression->AsObjectLiteral();
563 DCHECK(object_literal->builder()->is_simple());
564 return object_literal->builder()->boilerplate_description();
565 } else {
566 DCHECK(expression->IsArrayLiteral());
567 ArrayLiteral* array_literal = expression->AsArrayLiteral();
568 DCHECK(array_literal->builder()->is_simple());
569 return array_literal->builder()->boilerplate_description();
570 }
571 }
572 return isolate->factory()->uninitialized_value();
573}
576 Expression* expression, Isolate* isolate);
579 Expression* expression, LocalIsolate* isolate);
580
582 if (is_initialized()) return;
583
584 int constants_length =
586
587 // Fill in the literals.
589 bool is_holey = false;
591 DepthKind depth_acc = kShallow;
592 int array_index = 0;
593 for (; array_index < constants_length; array_index++) {
594 Expression* element = values_->at(array_index);
595 MaterializedLiteral* materialized_literal =
596 element->AsMaterializedLiteral();
597 if (materialized_literal != nullptr) {
599 depth_acc = kNotShallow;
600 }
601
602 if (!element->IsCompileTimeValue()) {
603 is_simple = false;
604
605 // Don't change kind here: non-compile time values resolve to an unknown
606 // elements kind, so we allow them to be considered as any one of them.
607
608 // TODO(leszeks): It would be nice to DCHECK here that GetBoilerplateValue
609 // will return IsUninitialized, but that would require being on the main
610 // thread which we may not be.
611 } else {
612 Literal* literal = element->AsLiteral();
613
614 if (!literal) {
615 // Only arrays and objects are compile-time values but not (primitive)
616 // literals.
617 DCHECK(element->IsObjectLiteral() || element->IsArrayLiteral());
619 } else {
620 switch (literal->type()) {
622 is_holey = true;
623 // The hole is allowed in holey double arrays (and holey Smi
624 // arrays), so ignore it as far as is_all_number is concerned.
625 break;
630 break;
631 case Literal::kSmi:
634 break;
635 case Literal::kBigInt:
636 case Literal::kString:
640 case Literal::kNull:
642 break;
643 }
644 }
645 }
646 }
647
648 if (is_holey) {
650 }
651
652 set_depth(depth_acc);
655
656 // Array literals always need an initial allocation site to properly track
657 // elements transitions.
659}
660
661template <typename IsolateT>
663 IsolateT* isolate) {
664 if (!boilerplate_description_.is_null()) return;
665
666 int constants_length =
669 bool use_doubles = IsDoubleElementsKind(kind);
670
672 if (use_doubles) {
673 elements = isolate->factory()->NewFixedDoubleArray(constants_length,
675 } else {
676 elements = isolate->factory()->NewFixedArrayWithHoles(constants_length,
678 }
679
680 // Fill in the literals.
681 int array_index = 0;
682 for (; array_index < constants_length; array_index++) {
683 Expression* element = values_->at(array_index);
684 DCHECK(!element->IsSpread());
685 if (use_doubles) {
686 Literal* literal = element->AsLiteral();
687
688 if (literal && literal->type() == Literal::kTheHole) {
690 DCHECK(IsTheHole(*GetBoilerplateValue(element, isolate), isolate));
691 Cast<FixedDoubleArray>(*elements)->set_the_hole(array_index);
692 continue;
693 } else if (literal && literal->IsNumber()) {
694 Cast<FixedDoubleArray>(*elements)->set(array_index,
695 literal->AsNumber());
696 } else {
697 DCHECK(
698 IsUninitialized(*GetBoilerplateValue(element, isolate), isolate));
699 Cast<FixedDoubleArray>(*elements)->set(array_index, 0);
700 }
701
702 } else {
703 MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
704 if (m_literal != nullptr) {
705 BuildConstants(isolate, m_literal);
706 }
707
708 // New handle scope here, needs to be after BuildConstants().
709 typename IsolateT::HandleScopeType scope(isolate);
710
711 Tagged<Object> boilerplate_value = *GetBoilerplateValue(element, isolate);
712 // We shouldn't allocate after creating the boilerplate value.
714
715 if (IsTheHole(boilerplate_value, isolate)) {
717 continue;
718 }
719
720 if (IsUninitialized(boilerplate_value, isolate)) {
721 boilerplate_value = Smi::zero();
722 }
723
726 boilerplate_value,
727 GetPtrComprCageBase(*elements))));
728
729 Cast<FixedArray>(*elements)->set(array_index, boilerplate_value);
730 }
731 } // namespace internal
732
733 // Simple and shallow arrays can be lazily copied, we transform the
734 // elements array to a copy-on-write array.
735 if (is_simple() && depth() == kShallow && array_index > 0 &&
737 elements->set_map_safe_transition(
738 isolate, ReadOnlyRoots(isolate).fixed_cow_array_map(), kReleaseStore);
739 }
740
742 isolate->factory()->NewArrayBoilerplateDescription(kind, elements);
743}
750
751 isolate);
752
754 return depth() <= kShallow &&
755 values_->length() <=
757}
758
760 if (IsArrayLiteral()) return AsArrayLiteral()->builder()->is_simple();
761 if (IsObjectLiteral()) return AsObjectLiteral()->builder()->is_simple();
762 DCHECK(IsRegExpLiteral());
763 return false;
764}
765
766// static
768 if (expr->IsArrayLiteral()) {
769 return expr->AsArrayLiteral()->builder()->InitDepthAndFlags();
770 }
771 if (expr->IsObjectLiteral()) {
772 return expr->AsObjectLiteral()->builder()->InitDepthAndFlags();
773 }
774 DCHECK(expr->IsRegExpLiteral());
775}
776
778
779) {
780 if (IsArrayLiteral()) {
781 return AsArrayLiteral()->builder()->needs_initial_allocation_site();
782 }
783 if (IsObjectLiteral()) {
784 return AsObjectLiteral()->builder()->needs_initial_allocation_site();
785 }
786 DCHECK(IsRegExpLiteral());
787 return false;
788}
789
790template <typename IsolateT>
792 MaterializedLiteral* expr) {
793 if (expr->IsArrayLiteral()) {
794 expr->AsArrayLiteral()->builder()->BuildBoilerplateDescription(isolate);
795 return;
796 }
797 if (expr->IsObjectLiteral()) {
798 expr->AsObjectLiteral()->builder()->BuildBoilerplateDescription(isolate);
799 return;
800 }
801 DCHECK(expr->IsRegExpLiteral());
802}
807
808template <typename IsolateT>
810 IsolateT* isolate) {
811 DirectHandle<FixedArray> raw_strings_handle =
812 isolate->factory()->NewFixedArray(this->raw_strings()->length(),
814 bool raw_and_cooked_match = true;
815 {
817 Tagged<FixedArray> raw_strings = *raw_strings_handle;
818
819 for (int i = 0; i < raw_strings->length(); ++i) {
820 if (this->raw_strings()->at(i) != this->cooked_strings()->at(i)) {
821 // If the AstRawStrings don't match, then neither should the allocated
822 // Strings, since the AstValueFactory should have deduplicated them
823 // already.
824 DCHECK_IMPLIES(this->cooked_strings()->at(i) != nullptr,
825 *this->cooked_strings()->at(i)->string() !=
826 *this->raw_strings()->at(i)->string());
827
828 raw_and_cooked_match = false;
829 }
830 raw_strings->set(i, *this->raw_strings()->at(i)->string());
831 }
832 }
833 DirectHandle<FixedArray> cooked_strings_handle = raw_strings_handle;
834 if (!raw_and_cooked_match) {
835 cooked_strings_handle = isolate->factory()->NewFixedArray(
838 Tagged<FixedArray> cooked_strings = *cooked_strings_handle;
839 ReadOnlyRoots roots(isolate);
840 for (int i = 0; i < cooked_strings->length(); ++i) {
841 if (this->cooked_strings()->at(i) != nullptr) {
842 cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
843 } else {
844 cooked_strings->set(i, roots.undefined_value(), SKIP_WRITE_BARRIER);
845 }
846 }
847 }
848 return isolate->factory()->NewTemplateObjectDescription(
849 raw_strings_handle, cooked_strings_handle);
850}
853 Isolate* isolate);
856 LocalIsolate* isolate);
857
859 // Add is not commutative due to potential for string addition.
860 return op == Token::kMul || op == Token::kBitAnd || op == Token::kBitOr ||
861 op == Token::kBitXor;
862}
863
864// Check for the pattern: x + 1.
866 Expression** expr, Tagged<Smi>* literal) {
867 if (right->IsSmiLiteral()) {
868 *expr = left;
869 *literal = right->AsLiteral()->AsSmiLiteral();
870 return true;
871 }
872 return false;
873}
874
881
882static bool IsVoidOfLiteral(Expression* expr) {
883 UnaryOperation* maybe_unary = expr->AsUnaryOperation();
884 return maybe_unary != nullptr && maybe_unary->op() == Token::kVoid &&
885 maybe_unary->expression()->IsLiteral();
886}
887
889 Expression* right,
890 Expression** expr,
891 Literal** literal) {
892 if (left->IsBooleanLiteral() && op == Token::kEqStrict) {
893 *expr = right;
894 *literal = left->AsLiteral();
895 return true;
896 }
897 return false;
898}
899
905
906// Check for the pattern: void <literal> equals <expression> or
907// undefined equals <expression>
909 Expression* right, Expression** expr) {
910 if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
911 *expr = right;
912 return true;
913 }
914 if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
915 *expr = right;
916 return true;
917 }
918 return false;
919}
920
925
926// Check for the pattern: null equals <expression>
928 Expression* right, Expression** expr) {
929 if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
930 *expr = right;
931 return true;
932 }
933 return false;
934}
935
940
942 Expression* right,
943 Expression** expr,
944 Literal** literal) {
945 if (Token::IsEqualityOp(op) && left->AsVariableProxy() &&
946 right->IsStringLiteral()) {
947 *expr = left->AsVariableProxy();
948 *literal = right->AsLiteral();
949 return true;
950 }
951 return false;
952}
953
960
962 int arguments_length = arguments_.length();
963 int first_spread_index = 0;
964 for (; first_spread_index < arguments_length; first_spread_index++) {
965 if (arguments_.at(first_spread_index)->IsSpread()) break;
966 }
968 if (first_spread_index == arguments_length - 1) {
970 } else {
971 DCHECK_LT(first_spread_index, arguments_length - 1);
973 }
975}
976
978 VariableProxy* proxy = expression()->AsVariableProxy();
979 if (proxy != nullptr) {
980 if (proxy->var()->IsUnallocated()) {
981 return GLOBAL_CALL;
982 } else if (proxy->var()->IsLookupSlot()) {
983 // Calls going through 'with' always use VariableMode::kDynamic rather
984 // than VariableMode::kDynamicLocal or VariableMode::kDynamicGlobal.
985 return proxy->var()->mode() == VariableMode::kDynamic ? WITH_CALL
986 : OTHER_CALL;
987 }
988 }
989
990 if (expression()->IsSuperCallReference()) return SUPER_CALL;
991
992 Property* property = expression()->AsProperty();
993 bool is_optional_chain = false;
994 if (V8_UNLIKELY(property == nullptr && expression()->IsOptionalChain())) {
995 is_optional_chain = true;
996 property = expression()->AsOptionalChain()->expression()->AsProperty();
997 }
998 if (property != nullptr) {
999 if (property->IsPrivateReference()) {
1000 if (is_optional_chain) return PRIVATE_OPTIONAL_CHAIN_CALL;
1001 return PRIVATE_CALL;
1002 }
1003 bool is_super = property->IsSuperAccess();
1004 // `super?.` is not syntactically valid, so a property load cannot be both
1005 // super and an optional chain.
1006 DCHECK(!is_super || !is_optional_chain);
1007 if (property->key()->IsPropertyName()) {
1008 if (is_super) return NAMED_SUPER_PROPERTY_CALL;
1009 if (is_optional_chain) return NAMED_OPTIONAL_CHAIN_PROPERTY_CALL;
1010 return NAMED_PROPERTY_CALL;
1011 } else {
1012 if (is_super) return KEYED_SUPER_PROPERTY_CALL;
1013 if (is_optional_chain) return KEYED_OPTIONAL_CHAIN_PROPERTY_CALL;
1014 return KEYED_PROPERTY_CALL;
1015 }
1016 }
1017
1018 return OTHER_CALL;
1019}
1020
1022 const ScopedPtrList<Statement>& statements)
1023 : label_(label), statements_(statements.ToConstVector(), zone) {}
1024
1026 if (type() != kString) return false;
1027 uint32_t index;
1028 return !string_->AsArrayIndex(&index);
1029}
1030
1031bool Literal::ToUint32(uint32_t* value) const {
1032 switch (type()) {
1033 case kString:
1034 return string_->AsArrayIndex(value);
1035 case kSmi:
1036 if (smi_ < 0) return false;
1037 *value = static_cast<uint32_t>(smi_);
1038 return true;
1039 case kHeapNumber:
1040 return DoubleToUint32IfEqualToSelf(AsNumber(), value);
1041 default:
1042 return false;
1043 }
1044}
1045
1046bool Literal::AsArrayIndex(uint32_t* value) const {
1047 return ToUint32(value) && *value != kMaxUInt32;
1048}
1049
1050template <typename IsolateT>
1052 switch (type()) {
1053 case kSmi:
1054 return direct_handle(Smi::FromInt(smi_), isolate);
1055 case kHeapNumber:
1056 return isolate->factory()->template NewNumber<AllocationType::kOld>(
1057 number_);
1058 case kString:
1059 return string_->string();
1060 case kConsString:
1061 return cons_string_->AllocateFlat(isolate);
1062 case kBoolean:
1063 return isolate->factory()->ToBoolean(boolean_);
1064 case kNull:
1065 return isolate->factory()->null_value();
1066 case kUndefined:
1067 return isolate->factory()->undefined_value();
1068 case kTheHole:
1069 return isolate->factory()->the_hole_value();
1070 case kBigInt:
1071 // This should never fail: the parser will never create a BigInt
1072 // literal that cannot be allocated.
1073 return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
1074 }
1075 UNREACHABLE();
1076}
1081
1082bool Literal::ToBooleanIsTrue() const {
1083 switch (type()) {
1084 case kSmi:
1085 return smi_ != 0;
1086 case kHeapNumber:
1087 return DoubleToBoolean(number_);
1088 case kString:
1089 return !string_->IsEmpty();
1090 case kConsString:
1091 return !cons_string_->IsEmpty();
1092 case kNull:
1093 case kUndefined:
1094 return false;
1095 case kBoolean:
1096 return boolean_;
1097 case kBigInt: {
1098 const char* bigint_str = bigint_.c_str();
1099 size_t length = strlen(bigint_str);
1100 DCHECK_GT(length, 0);
1101 if (length == 1 && bigint_str[0] == '0') return false;
1102 // Skip over any radix prefix; BigInts with length > 1 only
1103 // begin with zero if they include a radix.
1104 for (size_t i = (bigint_str[0] == '0') ? 2 : 0; i < length; ++i) {
1105 if (bigint_str[i] != '0') return true;
1106 }
1107 return false;
1108 }
1109 case kTheHole:
1110 UNREACHABLE();
1111 }
1112 UNREACHABLE();
1113}
1114
1115uint32_t Literal::Hash() {
1116 DCHECK(IsRawString() || IsNumber());
1117 uint32_t index;
1118 if (AsArrayIndex(&index)) {
1119 // Treat array indices as numbers, so that array indices are de-duped
1120 // correctly even if one of them is a string and the other is a number.
1121 return ComputeLongHash(index);
1122 }
1123 return IsRawString() ? AsRawString()->Hash()
1125}
1126
1127// static
1128bool Literal::Match(void* a, void* b) {
1129 Literal* x = static_cast<Literal*>(a);
1130 Literal* y = static_cast<Literal*>(b);
1131 uint32_t index_x;
1132 uint32_t index_y;
1133 if (x->AsArrayIndex(&index_x)) {
1134 return y->AsArrayIndex(&index_y) && index_x == index_y;
1135 }
1136 return (x->IsRawString() && y->IsRawString() &&
1137 x->AsRawString() == y->AsRawString()) ||
1138 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
1139}
1140
1142 int int_value;
1143 if (DoubleToSmiInteger(number, &int_value)) {
1144 return NewSmiLiteral(int_value, pos);
1145 }
1146 return zone_->New<Literal>(number, pos);
1147}
1148
1149} // namespace internal
1150} // namespace v8
#define LITERAL_NODE_LIST(V)
Definition ast.h:79
#define ITERATION_NODE_LIST(V)
Definition ast.h:49
#define RETURN_NODE(Node)
Definition ast.cc:45
#define V8_BASE_EXPORT
Definition base-export.h:26
Builtins::Kind kind
Definition builtins.cc:40
SourcePosition pos
static constexpr U encode(T value)
Definition bit-field.h:55
const ZonePtrList< Expression > * values_
Definition ast.h:1471
IndirectHandle< ArrayBoilerplateDescription > boilerplate_description_
Definition ast.h:1473
void BuildBoilerplateDescription(IsolateT *isolate)
Definition ast.cc:662
const ArrayLiteralBoilerplateBuilder * builder() const
Definition ast.h:1482
Token::Value op() const
Definition ast.h:2169
Assignment(NodeType type, Token::Value op, Expression *target, Expression *value, int pos)
Definition ast.cc:181
const char * c_str() const
Handle< String > AllocateFlat(IsolateT *isolate) const
std::forward_list< const AstRawString * > ToRawStrings() const
IndirectHandle< String > GetString(IsolateT *isolate)
Literal * NewNumberLiteral(double number, int pos)
Definition ast.cc:1141
Literal * NewSmiLiteral(int number, int pos)
Definition ast.h:3238
uint32_t bit_field_
Definition ast.h:178
MaterializedLiteral * AsMaterializedLiteral()
Definition ast.cc:57
int position() const
Definition ast.h:155
NodeType node_type() const
Definition ast.h:154
IterationStatement * AsIterationStatement()
Definition ast.cc:49
Token::Value op() const
Definition ast.h:1916
bool IsSmiLiteralOperation(Expression **subexpr, Tagged< Smi > *literal)
Definition ast.cc:875
void ComputeSpreadPosition()
Definition ast.cc:961
ZonePtrList< Expression > arguments_
Definition ast.h:1766
Expression * expression() const
Definition ast.h:1735
CallType GetCallType() const
Definition ast.cc:977
@ PRIVATE_OPTIONAL_CHAIN_CALL
Definition ast.h:1802
@ KEYED_OPTIONAL_CHAIN_PROPERTY_CALL
Definition ast.h:1798
@ NAMED_SUPER_PROPERTY_CALL
Definition ast.h:1799
@ KEYED_SUPER_PROPERTY_CALL
Definition ast.h:1800
@ NAMED_OPTIONAL_CHAIN_PROPERTY_CALL
Definition ast.h:1797
CaseClause(Zone *zone, Expression *label, const ScopedPtrList< Statement > &statements)
Definition ast.cc:1021
ClassLiteralProperty(Expression *key, Expression *value, Kind kind, bool is_static, bool is_computed_name, bool is_private)
Definition ast.cc:304
Token::Value op() const
Definition ast.h:2027
bool IsLiteralCompareEqualVariable(Expression **expr, Literal **literal)
Definition ast.cc:954
bool IsLiteralStrictCompareBoolean(Expression **expr, Literal **literal)
Definition ast.cc:900
bool IsLiteralCompareUndefined(Expression **expr)
Definition ast.cc:921
bool IsLiteralCompareNull(Expression **expr)
Definition ast.cc:936
static const int kMaximumClonedShallowObjectProperties
FunctionKind function_kind() const
Definition scopes.h:863
bool class_scope_has_private_brand() const
Definition scopes.h:1227
bool ShouldEagerCompile() const
Definition scopes.h:970
void set_has_inferred_function_name(bool value)
Definition scopes.h:1194
bool AllowsLazyCompilation() const
Definition scopes.cc:1424
void set_class_scope_has_private_brand(bool value)
Definition scopes.h:1224
bool ToBooleanIsFalse() const
Definition ast.cc:126
bool IsUndefinedLiteral() const
Definition ast.cc:106
bool IsAccessorFunctionDefinition() const
Definition ast.cc:150
bool IsBooleanLiteral() const
Definition ast.cc:91
bool IsValidReferenceExpression() const
Definition ast.cc:134
bool IsPrivateName() const
Definition ast.cc:130
bool IsNullOrUndefinedLiteral() const
Definition ast.h:258
bool IsAnonymousFunctionDefinition() const
Definition ast.cc:139
bool IsCompileTimeValue()
Definition ast.cc:99
V8_EXPORT_PRIVATE bool IsNumberLiteral() const
Definition ast.cc:71
bool IsStringLiteral() const
Definition ast.cc:75
bool IsConsStringLiteral() const
Definition ast.cc:79
bool ToBooleanIsTrue() const
Definition ast.cc:122
bool IsTheHoleLiteral() const
Definition ast.cc:95
bool IsNullLiteral() const
Definition ast.cc:87
bool IsLiteralButNotNullOrUndefined() const
Definition ast.cc:118
bool IsSmiLiteral() const
Definition ast.cc:67
bool IsConciseMethodDefinition() const
Definition ast.cc:146
bool IsPropertyName() const
Definition ast.cc:83
FunctionKind kind() const
Definition ast.cc:231
V8_EXPORT_PRIVATE void SetShouldEagerCompile()
Definition ast.cc:213
void set_raw_inferred_name(AstConsString *raw_inferred_name)
Definition ast.cc:187
Handle< SharedFunctionInfo > shared_function_info() const
Definition ast.h:2356
void set_class_scope_has_private_brand(bool value)
Definition ast.cc:272
V8_EXPORT_PRIVATE LanguageMode language_mode() const
Definition ast.cc:227
const AstConsString * raw_name_
Definition ast.h:2492
const AstConsString * raw_inferred_name()
Definition ast.h:2362
int start_position() const
Definition ast.cc:221
AstConsString * raw_inferred_name_
Definition ast.h:2495
IndirectHandle< SharedFunctionInfo > shared_function_info_
Definition ast.h:2496
bool class_scope_has_private_brand() const
Definition ast.cc:268
bool private_name_lookup_skips_outer_class() const
Definition ast.cc:264
Handle< String > GetInferredName(Isolate *isolate)
Definition ast.cc:194
DeclarationScope * scope() const
Definition ast.h:2315
V8_EXPORT_PRIVATE bool ShouldEagerCompile() const
Definition ast.cc:209
std::unique_ptr< char[]> GetDebugName() const
Definition ast.cc:233
void set_shared_function_info(Handle< SharedFunctionInfo > shared_function_info)
Definition ast.cc:202
const ZonePtrList< const AstRawString > * raw_strings() const
Definition ast.h:2885
Handle< TemplateObjectDescription > GetOrBuildDescription(IsolateT *isolate)
const ZonePtrList< const AstRawString > * cooked_strings() const
Definition ast.h:2882
void set_needs_initial_allocation_site(bool required)
Definition ast.h:1229
void set_boilerplate_descriptor_kind(ElementsKind kind)
Definition ast.h:1219
ElementsKind boilerplate_descriptor_kind() const
Definition ast.h:1189
int ComputeFlags(bool disable_mementos=false) const
Definition ast.h:1176
void set_is_simple(bool is_simple)
Definition ast.h:1215
static DirectHandle< Object > GetBoilerplateValue(Expression *expression, IsolateT *isolate)
Definition ast.cc:555
void BuildConstants(IsolateT *isolate, MaterializedLiteral *expr)
Definition ast.cc:791
static void InitDepthAndFlags(MaterializedLiteral *expr)
Definition ast.cc:767
void set_depth(DepthKind depth)
Definition ast.h:1224
Expression * key() const
Definition ast.h:1247
bool NeedsSetFunctionName() const
Definition ast.cc:298
bool is_computed_name() const
Definition ast.h:1250
bool AsArrayIndex(uint32_t *index) const
Definition ast.cc:1046
static bool Match(void *literal1, void *literal2)
Definition ast.cc:1128
bool ToUint32(uint32_t *value) const
Definition ast.cc:1031
const AstRawString * AsRawPropertyName()
Definition ast.h:980
DirectHandle< Object > BuildValue(IsolateT *isolate) const
Definition ast.cc:1051
uint32_t Hash()
Definition ast.cc:1115
Type type() const
Definition ast.h:967
AstBigInt bigint_
Definition ast.h:1086
bool IsRawString() const
Definition ast.h:1014
bool IsPropertyName() const
Definition ast.cc:1025
bool IsNumber() const
Definition ast.h:996
const AstRawString * AsRawString()
Definition ast.h:1015
V8_EXPORT_PRIVATE bool ToBooleanIsTrue() const
double AsNumber() const
Definition ast.h:997
const AstRawString * string_
Definition ast.h:1082
AstConsString * cons_string_
Definition ast.h:1083
void set_has_elements(bool has_elements)
Definition ast.h:1370
const ZonePtrList< Property > * properties() const
Definition ast.h:1326
void BuildBoilerplateDescription(IsolateT *isolate)
Definition ast.cc:478
DirectHandle< ObjectBoilerplateDescription > boilerplate_description() const
Definition ast.h:1318
IndirectHandle< ObjectBoilerplateDescription > boilerplate_description_
Definition ast.h:1381
int ComputeFlags(bool disable_mementos=false) const
Definition ast.cc:386
void set_has_null_protoype(bool has_null_prototype)
Definition ast.h:1376
void set_fast_elements(bool fast_elements)
Definition ast.h:1373
void set_emit_store(bool emit_store)
Definition ast.cc:332
ObjectLiteralProperty(Expression *key, Expression *value, Kind kind, bool is_computed_name)
Definition ast.cc:276
const ObjectLiteralBoilerplateBuilder * builder() const
Definition ast.h:1410
ZoneList< Property * > * properties()
Definition ast.h:1408
void CalculateEmitStore(Zone *zone)
Definition ast.cc:338
static ElementsKind OptimalElementsKind(Tagged< Object > obj, PtrComprCageBase cage_base)
bool private_name_lookup_skips_outer_class() const
Definition scopes.h:388
int end_position() const
Definition scopes.h:342
LanguageMode language_mode() const
Definition scopes.h:477
int start_position() const
Definition scopes.h:338
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
static constexpr Tagged< Smi > zero()
Definition smi.h:99
static bool IsEqualityOp(Value op)
Definition token.h:303
Expression * expression() const
Definition ast.h:1896
Token::Value op() const
Definition ast.h:1895
void BindTo(Variable *var)
Definition ast.cc:173
Variable * var() const
Definition ast.h:1517
bool is_assigned() const
Definition ast.h:1531
const AstRawString * raw_name() const
Definition ast.h:1513
VariableProxy(Variable *var, int start_position)
Definition ast.cc:154
void set_var(Variable *v)
Definition ast.h:1521
bool is_resolved() const
Definition ast.h:1542
const AstRawString * raw_name_
Definition ast.h:1629
VariableMode mode() const
Definition variables.h:66
bool is_this() const
Definition variables.h:251
bool IsLookupSlot() const
Definition variables.h:131
const AstRawString * raw_name() const
Definition variables.h:65
bool IsUnallocated() const
Definition variables.h:124
T * New(Args &&... args)
Definition zone.h:114
Register const value_
const PropertyKind kind_
Label label
#define EXPORT_TEMPLATE_DEFINE(export)
std::optional< TNode< JSArray > > a
const std::string property
ZoneVector< RpoNumber > & result
Label label_
#define SETTER(field)
int x
FunctionLiteral * literal
Definition liveedit.cc:294
int position
Definition liveedit.cc:290
constexpr uint64_t double_to_uint64(double d)
Definition double.h:17
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) Handle< TemplateObjectDescription > GetTemplateObject template static EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) Handle< TemplateObjectDescription > GetTemplateObject bool IsCommutativeOperationWithSmiLiteral(Token::Value op)
Definition ast.cc:858
static bool MatchSmiLiteralOperation(Expression *left, Expression *right, Expression **expr, Tagged< Smi > *literal)
Definition ast.cc:865
static bool MatchLiteralCompareNull(Expression *left, Token::Value op, Expression *right, Expression **expr)
Definition ast.cc:927
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
@ SKIP_WRITE_BARRIER
Definition objects.h:52
uint32_t ComputeLongHash(uint64_t key)
Definition utils.h:282
constexpr bool IsHoleyElementsKind(ElementsKind kind)
bool DoubleToUint32IfEqualToSelf(double value, uint32_t *uint32_value)
bool DoubleToSmiInteger(double value, int *smi_int_value)
bool DoubleToBoolean(double d)
Definition utils.cc:208
bool IsConciseMethod(FunctionKind kind)
kStaticElementsTemplateOffset kInstancePropertiesTemplateOffset Tagged< FixedArray >
MaybeHandle< BigInt > BigIntLiteral(IsolateT *isolate, const char *string)
bool IsAccessorFunction(FunctionKind kind)
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
Flag flags[]
Definition flags.cc:3797
static bool MatchLiteralCompareEqualVariable(Expression *left, Token::Value op, Expression *right, Expression **expr, Literal **literal)
Definition ast.cc:941
bool IsSmiOrObjectElementsKind(ElementsKind kind)
V8_INLINE PtrComprCageBase GetPtrComprCageBase()
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
static bool MatchLiteralCompareUndefined(Expression *left, Token::Value op, Expression *right, Expression **expr)
Definition ast.cc:908
static bool IsVoidOfLiteral(Expression *expr)
Definition ast.cc:882
static bool MatchLiteralStrictCompareBoolean(Expression *left, Token::Value op, Expression *right, Expression **expr, Literal **literal)
Definition ast.cc:888
constexpr bool IsDoubleElementsKind(ElementsKind kind)
ElementsKind GetMoreGeneralElementsKind(ElementsKind from_kind, ElementsKind to_kind)
constexpr uint32_t kMaxUInt32
Definition globals.h:387
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
static constexpr ReleaseStoreTag kReleaseStore
Definition globals.h:2910
Local< T > Handle
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_UNLIKELY(condition)
Definition v8config.h:660
#define GETTER(name)
wasm::ValueType type