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 
10 #include "src/ast/prettyprinter.h"
11 #include "src/ast/scopes.h"
12 #include "src/base/hashmap.h"
13 #include "src/base/logging.h"
14 #include "src/builtins/builtins-constructor.h"
15 #include "src/builtins/builtins.h"
16 #include "src/common/assert-scope.h"
17 #include "src/execution/off-thread-isolate.h"
18 #include "src/heap/off-thread-factory-inl.h"
19 #include "src/numbers/conversions-inl.h"
20 #include "src/numbers/double.h"
21 #include "src/objects/contexts.h"
22 #include "src/objects/elements-kind.h"
23 #include "src/objects/elements.h"
24 #include "src/objects/fixed-array.h"
25 #include "src/objects/literal-objects-inl.h"
26 #include "src/objects/literal-objects.h"
27 #include "src/objects/map.h"
28 #include "src/objects/objects-inl.h"
29 #include "src/objects/property-details.h"
30 #include "src/objects/property.h"
31 #include "src/strings/string-stream.h"
32 #include "src/zone/zone-list-inl.h"
33 
34 namespace v8 {
35 namespace internal {
36 
37 // ----------------------------------------------------------------------------
38 // Implementation of other node functionality.
39 
40 #ifdef DEBUG
41 
NameForNativeContextIntrinsicIndex(uint32_t idx)42 static const char* NameForNativeContextIntrinsicIndex(uint32_t idx) {
43   switch (idx) {
44 #define NATIVE_CONTEXT_FIELDS_IDX(NAME, Type, name) \
45   case Context::NAME:                               \
46     return #name;
47 
48     NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELDS_IDX)
49 #undef NATIVE_CONTEXT_FIELDS_IDX
50 
51     default:
52       break;
53   }
54 
55   return "UnknownIntrinsicIndex";
56 }
57 
Print(Isolate * isolate)58 void AstNode::Print(Isolate* isolate) {
59   AllowHandleDereference allow_deref;
60   AstPrinter::PrintOut(isolate, this);
61 }
62 
63 #endif  // DEBUG
64 
65 #define RETURN_NODE(Node) \
66   case k##Node:           \
67     return static_cast<Node*>(this);
68 
AsIterationStatement()69 IterationStatement* AstNode::AsIterationStatement() {
70   switch (node_type()) {
71     ITERATION_NODE_LIST(RETURN_NODE);
72     default:
73       return nullptr;
74   }
75 }
76 
AsMaterializedLiteral()77 MaterializedLiteral* AstNode::AsMaterializedLiteral() {
78   switch (node_type()) {
79     LITERAL_NODE_LIST(RETURN_NODE);
80     default:
81       return nullptr;
82   }
83 }
84 
85 #undef RETURN_NODE
86 
IsSmiLiteral() const87 bool Expression::IsSmiLiteral() const {
88   return IsLiteral() && AsLiteral()->type() == Literal::kSmi;
89 }
90 
IsNumberLiteral() const91 bool Expression::IsNumberLiteral() const {
92   return IsLiteral() && AsLiteral()->IsNumber();
93 }
94 
IsStringLiteral() const95 bool Expression::IsStringLiteral() const {
96   return IsLiteral() && AsLiteral()->type() == Literal::kString;
97 }
98 
IsPropertyName() const99 bool Expression::IsPropertyName() const {
100   return IsLiteral() && AsLiteral()->IsPropertyName();
101 }
102 
IsNullLiteral() const103 bool Expression::IsNullLiteral() const {
104   return IsLiteral() && AsLiteral()->type() == Literal::kNull;
105 }
106 
IsTheHoleLiteral() const107 bool Expression::IsTheHoleLiteral() const {
108   return IsLiteral() && AsLiteral()->type() == Literal::kTheHole;
109 }
110 
IsCompileTimeValue()111 bool Expression::IsCompileTimeValue() {
112   if (IsLiteral()) return true;
113   MaterializedLiteral* literal = AsMaterializedLiteral();
114   if (literal == nullptr) return false;
115   return literal->IsSimple();
116 }
117 
IsUndefinedLiteral() const118 bool Expression::IsUndefinedLiteral() const {
119   if (IsLiteral() && AsLiteral()->type() == Literal::kUndefined) return true;
120 
121   const VariableProxy* var_proxy = AsVariableProxy();
122   if (var_proxy == nullptr) return false;
123   Variable* var = var_proxy->var();
124   // The global identifier "undefined" is immutable. Everything
125   // else could be reassigned.
126   return var != nullptr && var->IsUnallocated() &&
127          var_proxy->raw_name()->IsOneByteEqualTo("undefined");
128 }
129 
IsLiteralButNotNullOrUndefined() const130 bool Expression::IsLiteralButNotNullOrUndefined() const {
131   return IsLiteral() && !IsNullOrUndefinedLiteral();
132 }
133 
ToBooleanIsTrue() const134 bool Expression::ToBooleanIsTrue() const {
135   return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
136 }
137 
ToBooleanIsFalse() const138 bool Expression::ToBooleanIsFalse() const {
139   return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
140 }
141 
IsPrivateName() const142 bool Expression::IsPrivateName() const {
143   return IsVariableProxy() && AsVariableProxy()->IsPrivateName();
144 }
145 
IsValidReferenceExpression() const146 bool Expression::IsValidReferenceExpression() const {
147   return IsProperty() ||
148          (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
149 }
150 
IsAnonymousFunctionDefinition() const151 bool Expression::IsAnonymousFunctionDefinition() const {
152   return (IsFunctionLiteral() &&
153           AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
154          (IsClassLiteral() &&
155           AsClassLiteral()->IsAnonymousFunctionDefinition());
156 }
157 
IsConciseMethodDefinition() const158 bool Expression::IsConciseMethodDefinition() const {
159   return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
160 }
161 
IsAccessorFunctionDefinition() const162 bool Expression::IsAccessorFunctionDefinition() const {
163   return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
164 }
165 
VariableProxy(Variable * var,int start_position)166 VariableProxy::VariableProxy(Variable* var, int start_position)
167     : Expression(start_position, kVariableProxy),
168       raw_name_(var->raw_name()),
169       next_unresolved_(nullptr) {
170   DCHECK(!var->is_this());
171   bit_field_ |= IsAssignedField::encode(false) |
172                 IsResolvedField::encode(false) |
173                 HoleCheckModeField::encode(HoleCheckMode::kElided);
174   BindTo(var);
175 }
176 
VariableProxy(const VariableProxy * copy_from)177 VariableProxy::VariableProxy(const VariableProxy* copy_from)
178     : Expression(copy_from->position(), kVariableProxy),
179       next_unresolved_(nullptr) {
180   bit_field_ = copy_from->bit_field_;
181   DCHECK(!copy_from->is_resolved());
182   raw_name_ = copy_from->raw_name_;
183 }
184 
BindTo(Variable * var)185 void VariableProxy::BindTo(Variable* var) {
186   DCHECK_EQ(raw_name(), var->raw_name());
187   set_var(var);
188   set_is_resolved();
189   var->set_is_used();
190   if (is_assigned()) var->SetMaybeAssigned();
191 }
192 
Assignment(NodeType node_type,Token::Value op,Expression * target,Expression * value,int pos)193 Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
194                        Expression* value, int pos)
195     : Expression(pos, node_type), target_(target), value_(value) {
196   bit_field_ |= TokenField::encode(op);
197 }
198 
set_inferred_name(Handle<String> inferred_name)199 void FunctionLiteral::set_inferred_name(Handle<String> inferred_name) {
200   DCHECK(!inferred_name.is_null());
201   inferred_name_ = inferred_name;
202   DCHECK(raw_inferred_name_ == nullptr || raw_inferred_name_->IsEmpty());
203   raw_inferred_name_ = nullptr;
204   scope()->set_has_inferred_function_name(true);
205 }
206 
set_raw_inferred_name(AstConsString * raw_inferred_name)207 void FunctionLiteral::set_raw_inferred_name(AstConsString* raw_inferred_name) {
208   DCHECK_NOT_NULL(raw_inferred_name);
209   raw_inferred_name_ = raw_inferred_name;
210   DCHECK(inferred_name_.is_null());
211   inferred_name_ = Handle<String>();
212   scope()->set_has_inferred_function_name(true);
213 }
214 
ShouldEagerCompile() const215 bool FunctionLiteral::ShouldEagerCompile() const {
216   return scope()->ShouldEagerCompile();
217 }
218 
SetShouldEagerCompile()219 void FunctionLiteral::SetShouldEagerCompile() {
220   scope()->set_should_eager_compile();
221 }
222 
AllowsLazyCompilation()223 bool FunctionLiteral::AllowsLazyCompilation() {
224   return scope()->AllowsLazyCompilation();
225 }
226 
SafeToSkipArgumentsAdaptor() const227 bool FunctionLiteral::SafeToSkipArgumentsAdaptor() const {
228   return language_mode() == LanguageMode::kStrict &&
229          scope()->arguments() == nullptr &&
230          scope()->rest_parameter() == nullptr;
231 }
232 
start_position() const233 int FunctionLiteral::start_position() const {
234   return scope()->start_position();
235 }
236 
end_position() const237 int FunctionLiteral::end_position() const { return scope()->end_position(); }
238 
language_mode() const239 LanguageMode FunctionLiteral::language_mode() const {
240   return scope()->language_mode();
241 }
242 
kind() const243 FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
244 
NeedsHomeObject(Expression * expr)245 bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
246   if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
247   DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
248   return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
249 }
250 
GetDebugName() const251 std::unique_ptr<char[]> FunctionLiteral::GetDebugName() const {
252   const AstConsString* cons_string;
253   if (raw_name_ != nullptr && !raw_name_->IsEmpty()) {
254     cons_string = raw_name_;
255   } else if (raw_inferred_name_ != nullptr && !raw_inferred_name_->IsEmpty()) {
256     cons_string = raw_inferred_name_;
257   } else if (!inferred_name_.is_null()) {
258     AllowHandleDereference allow_deref;
259     return inferred_name_->ToCString();
260   } else {
261     char* empty_str = new char[1];
262     empty_str[0] = 0;
263     return std::unique_ptr<char[]>(empty_str);
264   }
265 
266   // TODO(rmcilroy): Deal with two-character strings.
267   std::vector<char> result_vec;
268   std::forward_list<const AstRawString*> strings = cons_string->ToRawStrings();
269   for (const AstRawString* string : strings) {
270     if (!string->is_one_byte()) break;
271     for (int i = 0; i < string->length(); i++) {
272       result_vec.push_back(string->raw_data()[i]);
273     }
274   }
275   std::unique_ptr<char[]> result(new char[result_vec.size() + 1]);
276   memcpy(result.get(), result_vec.data(), result_vec.size());
277   result[result_vec.size()] = '\0';
278   return result;
279 }
280 
private_name_lookup_skips_outer_class() const281 bool FunctionLiteral::private_name_lookup_skips_outer_class() const {
282   return scope()->private_name_lookup_skips_outer_class();
283 }
284 
ObjectLiteralProperty(Expression * key,Expression * value,Kind kind,bool is_computed_name)285 ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
286                                              Kind kind, bool is_computed_name)
287     : LiteralProperty(key, value, is_computed_name),
288       kind_(kind),
289       emit_store_(true) {}
290 
ObjectLiteralProperty(AstValueFactory * ast_value_factory,Expression * key,Expression * value,bool is_computed_name)291 ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
292                                              Expression* key, Expression* value,
293                                              bool is_computed_name)
294     : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
295   if (!is_computed_name && key->AsLiteral()->IsString() &&
296       key->AsLiteral()->AsRawString() == ast_value_factory->proto_string()) {
297     kind_ = PROTOTYPE;
298   } else if (value_->AsMaterializedLiteral() != nullptr) {
299     kind_ = MATERIALIZED_LITERAL;
300   } else if (value_->IsLiteral()) {
301     kind_ = CONSTANT;
302   } else {
303     kind_ = COMPUTED;
304   }
305 }
306 
NeedsSetFunctionName() const307 bool LiteralProperty::NeedsSetFunctionName() const {
308   return is_computed_name() && (value_->IsAnonymousFunctionDefinition() ||
309                                 value_->IsConciseMethodDefinition() ||
310                                 value_->IsAccessorFunctionDefinition());
311 }
312 
ClassLiteralProperty(Expression * key,Expression * value,Kind kind,bool is_static,bool is_computed_name,bool is_private)313 ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
314                                            Kind kind, bool is_static,
315                                            bool is_computed_name,
316                                            bool is_private)
317     : LiteralProperty(key, value, is_computed_name),
318       kind_(kind),
319       is_static_(is_static),
320       is_private_(is_private),
321       private_or_computed_name_var_(nullptr) {}
322 
IsCompileTimeValue() const323 bool ObjectLiteral::Property::IsCompileTimeValue() const {
324   return kind_ == CONSTANT ||
325          (kind_ == MATERIALIZED_LITERAL && value_->IsCompileTimeValue());
326 }
327 
set_emit_store(bool emit_store)328 void ObjectLiteral::Property::set_emit_store(bool emit_store) {
329   emit_store_ = emit_store;
330 }
331 
emit_store() const332 bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
333 
CalculateEmitStore(Zone * zone)334 void ObjectLiteral::CalculateEmitStore(Zone* zone) {
335   const auto GETTER = ObjectLiteral::Property::GETTER;
336   const auto SETTER = ObjectLiteral::Property::SETTER;
337 
338   ZoneAllocationPolicy allocator(zone);
339 
340   CustomMatcherZoneHashMap table(
341       Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
342   for (int i = properties()->length() - 1; i >= 0; i--) {
343     ObjectLiteral::Property* property = properties()->at(i);
344     if (property->is_computed_name()) continue;
345     if (property->IsPrototype()) continue;
346     Literal* literal = property->key()->AsLiteral();
347     DCHECK(!literal->IsNullLiteral());
348 
349     uint32_t hash = literal->Hash();
350     ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
351     if (entry->value == nullptr) {
352       entry->value = property;
353     } else {
354       // We already have a later definition of this property, so we don't need
355       // to emit a store for the current one.
356       //
357       // There are two subtleties here.
358       //
359       // (1) Emitting a store might actually be incorrect. For example, in {get
360       // foo() {}, foo: 42}, the getter store would override the data property
361       // (which, being a non-computed compile-time valued property, is already
362       // part of the initial literal object.
363       //
364       // (2) If the later definition is an accessor (say, a getter), and the
365       // current definition is a complementary accessor (here, a setter), then
366       // we still must emit a store for the current definition.
367 
368       auto later_kind =
369           static_cast<ObjectLiteral::Property*>(entry->value)->kind();
370       bool complementary_accessors =
371           (property->kind() == GETTER && later_kind == SETTER) ||
372           (property->kind() == SETTER && later_kind == GETTER);
373       if (!complementary_accessors) {
374         property->set_emit_store(false);
375         if (later_kind == GETTER || later_kind == SETTER) {
376           entry->value = property;
377         }
378       }
379     }
380   }
381 }
382 
InitFlagsForPendingNullPrototype(int i)383 void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
384   // We still check for __proto__:null after computed property names.
385   for (; i < properties()->length(); i++) {
386     if (properties()->at(i)->IsNullPrototype()) {
387       set_has_null_protoype(true);
388       break;
389     }
390   }
391 }
392 
InitDepthAndFlags()393 int ObjectLiteral::InitDepthAndFlags() {
394   if (is_initialized()) return depth();
395   bool is_simple = true;
396   bool has_seen_prototype = false;
397   bool needs_initial_allocation_site = false;
398   int depth_acc = 1;
399   uint32_t nof_properties = 0;
400   uint32_t elements = 0;
401   uint32_t max_element_index = 0;
402   for (int i = 0; i < properties()->length(); i++) {
403     ObjectLiteral::Property* property = properties()->at(i);
404     if (property->IsPrototype()) {
405       has_seen_prototype = true;
406       // __proto__:null has no side-effects and is set directly on the
407       // boilerplate.
408       if (property->IsNullPrototype()) {
409         set_has_null_protoype(true);
410         continue;
411       }
412       DCHECK(!has_null_prototype());
413       is_simple = false;
414       continue;
415     }
416     if (nof_properties == boilerplate_properties_) {
417       DCHECK(property->is_computed_name());
418       is_simple = false;
419       if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
420       break;
421     }
422     DCHECK(!property->is_computed_name());
423 
424     MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
425     if (literal != nullptr) {
426       int subliteral_depth = literal->InitDepthAndFlags() + 1;
427       if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
428       needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
429     }
430 
431     Literal* key = property->key()->AsLiteral();
432     Expression* value = property->value();
433 
434     bool is_compile_time_value = value->IsCompileTimeValue();
435     is_simple = is_simple && is_compile_time_value;
436 
437     // Keep track of the number of elements in the object literal and
438     // the largest element index.  If the largest element index is
439     // much larger than the number of elements, creating an object
440     // literal with fast elements will be a waste of space.
441     uint32_t element_index = 0;
442     if (key->AsArrayIndex(&element_index)) {
443       max_element_index = Max(element_index, max_element_index);
444       elements++;
445     } else {
446       DCHECK(key->IsPropertyName());
447     }
448 
449     nof_properties++;
450   }
451 
452   set_depth(depth_acc);
453   set_is_simple(is_simple);
454   set_needs_initial_allocation_site(needs_initial_allocation_site);
455   set_has_elements(elements > 0);
456   set_fast_elements((max_element_index <= 32) ||
457                     ((2 * elements) >= max_element_index));
458   return depth_acc;
459 }
460 
461 template <typename LocalIsolate>
BuildBoilerplateDescription(LocalIsolate * isolate)462 void ObjectLiteral::BuildBoilerplateDescription(LocalIsolate* isolate) {
463   if (!boilerplate_description_.is_null()) return;
464 
465   int index_keys = 0;
466   bool has_seen_proto = false;
467   for (int i = 0; i < properties()->length(); i++) {
468     ObjectLiteral::Property* property = properties()->at(i);
469     if (property->IsPrototype()) {
470       has_seen_proto = true;
471       continue;
472     }
473     if (property->is_computed_name()) continue;
474 
475     Literal* key = property->key()->AsLiteral();
476     if (!key->IsPropertyName()) index_keys++;
477   }
478 
479   Handle<ObjectBoilerplateDescription> boilerplate_description =
480       isolate->factory()->NewObjectBoilerplateDescription(
481           boilerplate_properties_, properties()->length(), index_keys,
482           has_seen_proto);
483 
484   int position = 0;
485   for (int i = 0; i < properties()->length(); i++) {
486     ObjectLiteral::Property* property = properties()->at(i);
487     if (property->IsPrototype()) continue;
488 
489     if (static_cast<uint32_t>(position) == boilerplate_properties_) {
490       DCHECK(property->is_computed_name());
491       break;
492     }
493     DCHECK(!property->is_computed_name());
494 
495     MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
496     if (m_literal != nullptr) {
497       m_literal->BuildConstants(isolate);
498     }
499 
500     // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
501     // value for COMPUTED properties, the real value is filled in at
502     // runtime. The enumeration order is maintained.
503     Literal* key_literal = property->key()->AsLiteral();
504     uint32_t element_index = 0;
505     Handle<Object> key =
506         key_literal->AsArrayIndex(&element_index)
507             ? isolate->factory()
508                   ->template NewNumberFromUint<AllocationType::kOld>(
509                       element_index)
510             : Handle<Object>::cast(key_literal->AsRawPropertyName()->string());
511 
512     Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
513 
514     // Add name, value pair to the fixed array.
515     boilerplate_description->set_key_value(position++, *key, *value);
516   }
517 
518   boilerplate_description->set_flags(EncodeLiteralType());
519 
520   boilerplate_description_ = boilerplate_description;
521 }
522 template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) void ObjectLiteral::
523     BuildBoilerplateDescription(Isolate* isolate);
524 template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) void ObjectLiteral::
525     BuildBoilerplateDescription(OffThreadIsolate* isolate);
526 
IsFastCloningSupported() const527 bool ObjectLiteral::IsFastCloningSupported() const {
528   // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
529   // literals don't support copy-on-write (COW) elements for now.
530   // TODO(mvstanton): make object literals support COW elements.
531   return fast_elements() && is_shallow() &&
532          properties_count() <=
533              ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
534 }
535 
InitDepthAndFlags()536 int ArrayLiteral::InitDepthAndFlags() {
537   if (is_initialized()) return depth();
538 
539   int constants_length =
540       first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
541 
542   // Fill in the literals.
543   bool is_simple = first_spread_index_ < 0;
544   bool is_holey = false;
545   ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
546   int depth_acc = 1;
547   int array_index = 0;
548   for (; array_index < constants_length; array_index++) {
549     Expression* element = values()->at(array_index);
550     MaterializedLiteral* literal = element->AsMaterializedLiteral();
551     if (literal != nullptr) {
552       int subliteral_depth = literal->InitDepthAndFlags() + 1;
553       if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
554     }
555 
556     if (!element->IsCompileTimeValue()) {
557       is_simple = false;
558 
559       // Don't change kind here: non-compile time values resolve to an unknown
560       // elements kind, so we allow them to be considered as any one of them.
561 
562       // TODO(leszeks): It would be nice to DCHECK here that GetBoilerplateValue
563       // will return IsUninitialized, but that would require being on the main
564       // thread which we may not be.
565     } else {
566       Literal* literal = element->AsLiteral();
567 
568       if (!literal) {
569         // Only arrays and objects are compile-time values but not (primitive)
570         // literals.
571         DCHECK(element->IsObjectLiteral() || element->IsArrayLiteral());
572         kind = PACKED_ELEMENTS;
573       } else {
574         switch (literal->type()) {
575           case Literal::kTheHole:
576             is_holey = true;
577             // The hole is allowed in holey double arrays (and holey Smi
578             // arrays), so ignore it as far as is_all_number is concerned.
579             break;
580           case Literal::kHeapNumber:
581             if (kind == PACKED_SMI_ELEMENTS) kind = PACKED_DOUBLE_ELEMENTS;
582             DCHECK_EQ(kind,
583                       GetMoreGeneralElementsKind(kind, PACKED_DOUBLE_ELEMENTS));
584             break;
585           case Literal::kSmi:
586             DCHECK_EQ(kind,
587                       GetMoreGeneralElementsKind(kind, PACKED_SMI_ELEMENTS));
588             break;
589           case Literal::kBigInt:
590           case Literal::kString:
591           case Literal::kSymbol:
592           case Literal::kBoolean:
593           case Literal::kUndefined:
594           case Literal::kNull:
595             kind = PACKED_ELEMENTS;
596             break;
597         }
598       }
599     }
600   }
601 
602   if (is_holey) {
603     kind = GetHoleyElementsKind(kind);
604   }
605 
606   set_depth(depth_acc);
607   set_is_simple(is_simple);
608   set_boilerplate_descriptor_kind(kind);
609 
610   // Array literals always need an initial allocation site to properly track
611   // elements transitions.
612   set_needs_initial_allocation_site(true);
613   return depth_acc;
614 }
615 
616 template <typename LocalIsolate>
BuildBoilerplateDescription(LocalIsolate * isolate)617 void ArrayLiteral::BuildBoilerplateDescription(LocalIsolate* isolate) {
618   if (!boilerplate_description_.is_null()) return;
619 
620   int constants_length =
621       first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
622   ElementsKind kind = boilerplate_descriptor_kind();
623   bool use_doubles = IsDoubleElementsKind(kind);
624 
625   Handle<FixedArrayBase> elements;
626   if (use_doubles) {
627     elements = isolate->factory()->NewFixedDoubleArray(constants_length,
628                                                        AllocationType::kOld);
629   } else {
630     elements = isolate->factory()->NewFixedArrayWithHoles(constants_length,
631                                                           AllocationType::kOld);
632   }
633 
634   // Fill in the literals.
635   int array_index = 0;
636   for (; array_index < constants_length; array_index++) {
637     Expression* element = values()->at(array_index);
638     DCHECK(!element->IsSpread());
639     if (use_doubles) {
640       Literal* literal = element->AsLiteral();
641 
642       if (literal && literal->type() == Literal::kTheHole) {
643         DCHECK(IsHoleyElementsKind(kind));
644         DCHECK(GetBoilerplateValue(element, isolate)->IsTheHole(isolate));
645         FixedDoubleArray::cast(*elements).set_the_hole(array_index);
646         continue;
647       } else if (literal && literal->IsNumber()) {
648         FixedDoubleArray::cast(*elements).set(array_index, literal->AsNumber());
649       } else {
650         DCHECK(GetBoilerplateValue(element, isolate)->IsUninitialized(isolate));
651         FixedDoubleArray::cast(*elements).set(array_index, 0);
652       }
653 
654     } else {
655       MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
656       if (m_literal != nullptr) {
657         m_literal->BuildConstants(isolate);
658       }
659 
660       // New handle scope here, needs to be after BuildContants().
661       typename LocalIsolate::HandleScopeType scope(isolate);
662 
663       Object boilerplate_value = *GetBoilerplateValue(element, isolate);
664       // We shouldn't allocate after creating the boilerplate value.
665       DisallowHeapAllocation no_gc;
666 
667       if (boilerplate_value.IsTheHole(isolate)) {
668         DCHECK(IsHoleyElementsKind(kind));
669         continue;
670       }
671 
672       if (boilerplate_value.IsUninitialized(isolate)) {
673         boilerplate_value = Smi::zero();
674       }
675 
676       DCHECK_EQ(
677           boilerplate_descriptor_kind(),
678           GetMoreGeneralElementsKind(boilerplate_descriptor_kind(),
679                                      boilerplate_value.OptimalElementsKind(
680                                          GetIsolateForPtrCompr(*elements))));
681 
682       FixedArray::cast(*elements).set(array_index, boilerplate_value);
683     }
684   }  // namespace internal
685 
686   // Simple and shallow arrays can be lazily copied, we transform the
687   // elements array to a copy-on-write array.
688   if (is_simple() && depth() == 1 && array_index > 0 &&
689       IsSmiOrObjectElementsKind(kind)) {
690     elements->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
691   }
692 
693   boilerplate_description_ =
694       isolate->factory()->NewArrayBoilerplateDescription(kind, elements);
695 }
696 template EXPORT_TEMPLATE_DEFINE(
697     V8_BASE_EXPORT) void ArrayLiteral::BuildBoilerplateDescription(Isolate*
698                                                                        isolate);
699 template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) void ArrayLiteral::
700     BuildBoilerplateDescription(OffThreadIsolate* isolate);
701 
IsFastCloningSupported() const702 bool ArrayLiteral::IsFastCloningSupported() const {
703   return depth() <= 1 &&
704          values_.length() <=
705              ConstructorBuiltins::kMaximumClonedShallowArrayElements;
706 }
707 
IsSimple() const708 bool MaterializedLiteral::IsSimple() const {
709   if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
710   if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
711   DCHECK(IsRegExpLiteral());
712   return false;
713 }
714 
715 template <typename LocalIsolate>
GetBoilerplateValue(Expression * expression,LocalIsolate * isolate)716 Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
717                                                         LocalIsolate* isolate) {
718   if (expression->IsLiteral()) {
719     return expression->AsLiteral()->BuildValue(isolate);
720   }
721   if (expression->IsCompileTimeValue()) {
722     if (expression->IsObjectLiteral()) {
723       ObjectLiteral* object_literal = expression->AsObjectLiteral();
724       DCHECK(object_literal->is_simple());
725       return object_literal->boilerplate_description();
726     } else {
727       DCHECK(expression->IsArrayLiteral());
728       ArrayLiteral* array_literal = expression->AsArrayLiteral();
729       DCHECK(array_literal->is_simple());
730       return array_literal->boilerplate_description();
731     }
732   }
733   return isolate->factory()->uninitialized_value();
734 }
735 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
736     Handle<Object> MaterializedLiteral::GetBoilerplateValue(
737         Expression* expression, Isolate* isolate);
738 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
739     Handle<Object> MaterializedLiteral::GetBoilerplateValue(
740         Expression* expression, OffThreadIsolate* isolate);
741 
InitDepthAndFlags()742 int MaterializedLiteral::InitDepthAndFlags() {
743   if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
744   if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
745   DCHECK(IsRegExpLiteral());
746   return 1;
747 }
748 
NeedsInitialAllocationSite()749 bool MaterializedLiteral::NeedsInitialAllocationSite() {
750   if (IsArrayLiteral()) {
751     return AsArrayLiteral()->needs_initial_allocation_site();
752   }
753   if (IsObjectLiteral()) {
754     return AsObjectLiteral()->needs_initial_allocation_site();
755   }
756   DCHECK(IsRegExpLiteral());
757   return false;
758 }
759 
760 template <typename LocalIsolate>
BuildConstants(LocalIsolate * isolate)761 void MaterializedLiteral::BuildConstants(LocalIsolate* isolate) {
762   if (IsArrayLiteral()) {
763     AsArrayLiteral()->BuildBoilerplateDescription(isolate);
764     return;
765   }
766   if (IsObjectLiteral()) {
767     AsObjectLiteral()->BuildBoilerplateDescription(isolate);
768     return;
769   }
770   DCHECK(IsRegExpLiteral());
771 }
772 template EXPORT_TEMPLATE_DEFINE(
773     V8_BASE_EXPORT) void MaterializedLiteral::BuildConstants(Isolate* isolate);
774 template EXPORT_TEMPLATE_DEFINE(
775     V8_BASE_EXPORT) void MaterializedLiteral::BuildConstants(OffThreadIsolate*
776                                                                  isolate);
777 
778 template <typename LocalIsolate>
GetOrBuildDescription(LocalIsolate * isolate)779 Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
780     LocalIsolate* isolate) {
781   Handle<FixedArray> raw_strings = isolate->factory()->NewFixedArray(
782       this->raw_strings()->length(), AllocationType::kOld);
783   bool raw_and_cooked_match = true;
784   for (int i = 0; i < raw_strings->length(); ++i) {
785     if (this->raw_strings()->at(i) != this->cooked_strings()->at(i)) {
786       // If the AstRawStrings don't match, then neither should the allocated
787       // Strings, since the AstValueFactory should have deduplicated them
788       // already.
789       DCHECK_IMPLIES(this->cooked_strings()->at(i) != nullptr,
790                      *this->cooked_strings()->at(i)->string() !=
791                          *this->raw_strings()->at(i)->string());
792 
793       raw_and_cooked_match = false;
794     }
795     raw_strings->set(i, *this->raw_strings()->at(i)->string());
796   }
797   Handle<FixedArray> cooked_strings = raw_strings;
798   if (!raw_and_cooked_match) {
799     cooked_strings = isolate->factory()->NewFixedArray(
800         this->cooked_strings()->length(), AllocationType::kOld);
801     for (int i = 0; i < cooked_strings->length(); ++i) {
802       if (this->cooked_strings()->at(i) != nullptr) {
803         cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
804       } else {
805         cooked_strings->set(i, ReadOnlyRoots(isolate).undefined_value());
806       }
807     }
808   }
809   return isolate->factory()->NewTemplateObjectDescription(raw_strings,
810                                                           cooked_strings);
811 }
812 template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT)
813     Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
814         Isolate* isolate);
815 template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT)
816     Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
817         OffThreadIsolate* isolate);
818 
IsCommutativeOperationWithSmiLiteral(Token::Value op)819 static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
820   // Add is not commutative due to potential for string addition.
821   return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
822          op == Token::BIT_XOR;
823 }
824 
825 // Check for the pattern: x + 1.
MatchSmiLiteralOperation(Expression * left,Expression * right,Expression ** expr,Smi * literal)826 static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
827                                      Expression** expr, Smi* literal) {
828   if (right->IsSmiLiteral()) {
829     *expr = left;
830     *literal = right->AsLiteral()->AsSmiLiteral();
831     return true;
832   }
833   return false;
834 }
835 
IsSmiLiteralOperation(Expression ** subexpr,Smi * literal)836 bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
837                                             Smi* literal) {
838   return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
839          (IsCommutativeOperationWithSmiLiteral(op()) &&
840           MatchSmiLiteralOperation(right_, left_, subexpr, literal));
841 }
842 
IsTypeof(Expression * expr)843 static bool IsTypeof(Expression* expr) {
844   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
845   return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
846 }
847 
848 // Check for the pattern: typeof <expression> equals <string literal>.
MatchLiteralCompareTypeof(Expression * left,Token::Value op,Expression * right,Expression ** expr,Literal ** literal)849 static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
850                                       Expression* right, Expression** expr,
851                                       Literal** literal) {
852   if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
853     *expr = left->AsUnaryOperation()->expression();
854     *literal = right->AsLiteral();
855     return true;
856   }
857   return false;
858 }
859 
IsLiteralCompareTypeof(Expression ** expr,Literal ** literal)860 bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
861                                               Literal** literal) {
862   return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
863          MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
864 }
865 
IsVoidOfLiteral(Expression * expr)866 static bool IsVoidOfLiteral(Expression* expr) {
867   UnaryOperation* maybe_unary = expr->AsUnaryOperation();
868   return maybe_unary != nullptr && maybe_unary->op() == Token::VOID &&
869          maybe_unary->expression()->IsLiteral();
870 }
871 
872 // Check for the pattern: void <literal> equals <expression> or
873 // undefined equals <expression>
MatchLiteralCompareUndefined(Expression * left,Token::Value op,Expression * right,Expression ** expr)874 static bool MatchLiteralCompareUndefined(Expression* left, Token::Value op,
875                                          Expression* right, Expression** expr) {
876   if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
877     *expr = right;
878     return true;
879   }
880   if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
881     *expr = right;
882     return true;
883   }
884   return false;
885 }
886 
IsLiteralCompareUndefined(Expression ** expr)887 bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
888   return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
889          MatchLiteralCompareUndefined(right_, op(), left_, expr);
890 }
891 
892 // Check for the pattern: null equals <expression>
MatchLiteralCompareNull(Expression * left,Token::Value op,Expression * right,Expression ** expr)893 static bool MatchLiteralCompareNull(Expression* left, Token::Value op,
894                                     Expression* right, Expression** expr) {
895   if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
896     *expr = right;
897     return true;
898   }
899   return false;
900 }
901 
IsLiteralCompareNull(Expression ** expr)902 bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
903   return MatchLiteralCompareNull(left_, op(), right_, expr) ||
904          MatchLiteralCompareNull(right_, op(), left_, expr);
905 }
906 
GetCallType() const907 Call::CallType Call::GetCallType() const {
908   VariableProxy* proxy = expression()->AsVariableProxy();
909   if (proxy != nullptr) {
910     if (proxy->var()->IsUnallocated()) {
911       return GLOBAL_CALL;
912     } else if (proxy->var()->IsLookupSlot()) {
913       // Calls going through 'with' always use VariableMode::kDynamic rather
914       // than VariableMode::kDynamicLocal or VariableMode::kDynamicGlobal.
915       return proxy->var()->mode() == VariableMode::kDynamic ? WITH_CALL
916                                                             : OTHER_CALL;
917     }
918   }
919 
920   if (expression()->IsSuperCallReference()) return SUPER_CALL;
921 
922   Property* property = expression()->AsProperty();
923   bool is_optional_chain = false;
924   if (V8_UNLIKELY(property == nullptr && expression()->IsOptionalChain())) {
925     is_optional_chain = true;
926     property = expression()->AsOptionalChain()->expression()->AsProperty();
927   }
928   if (property != nullptr) {
929     if (property->IsPrivateReference()) {
930       return PRIVATE_CALL;
931     }
932     bool is_super = property->IsSuperAccess();
933     // `super?.` is not syntactically valid, so a property load cannot be both
934     // super and an optional chain.
935     DCHECK(!is_super || !is_optional_chain);
936     if (property->key()->IsPropertyName()) {
937       if (is_super) return NAMED_SUPER_PROPERTY_CALL;
938       if (is_optional_chain) return NAMED_OPTIONAL_CHAIN_PROPERTY_CALL;
939       return NAMED_PROPERTY_CALL;
940     } else {
941       if (is_super) return KEYED_SUPER_PROPERTY_CALL;
942       if (is_optional_chain) return KEYED_OPTIONAL_CHAIN_PROPERTY_CALL;
943       return KEYED_PROPERTY_CALL;
944     }
945   }
946 
947   return OTHER_CALL;
948 }
949 
CaseClause(Zone * zone,Expression * label,const ScopedPtrList<Statement> & statements)950 CaseClause::CaseClause(Zone* zone, Expression* label,
951                        const ScopedPtrList<Statement>& statements)
952     : label_(label), statements_(0, nullptr) {
953   statements.CopyTo(&statements_, zone);
954 }
955 
IsPropertyName() const956 bool Literal::IsPropertyName() const {
957   if (type() != kString) return false;
958   uint32_t index;
959   return !string_->AsArrayIndex(&index);
960 }
961 
ToUint32(uint32_t * value) const962 bool Literal::ToUint32(uint32_t* value) const {
963   switch (type()) {
964     case kString:
965       return string_->AsArrayIndex(value);
966     case kSmi:
967       if (smi_ < 0) return false;
968       *value = static_cast<uint32_t>(smi_);
969       return true;
970     case kHeapNumber:
971       return DoubleToUint32IfEqualToSelf(AsNumber(), value);
972     default:
973       return false;
974   }
975 }
976 
AsArrayIndex(uint32_t * value) const977 bool Literal::AsArrayIndex(uint32_t* value) const {
978   return ToUint32(value) && *value != kMaxUInt32;
979 }
980 
981 template <typename LocalIsolate>
BuildValue(LocalIsolate * isolate) const982 Handle<Object> Literal::BuildValue(LocalIsolate* isolate) const {
983   switch (type()) {
984     case kSmi:
985       return handle(Smi::FromInt(smi_), isolate);
986     case kHeapNumber:
987       return isolate->factory()->template NewNumber<AllocationType::kOld>(
988           number_);
989     case kString:
990       return string_->string();
991     case kSymbol:
992       return isolate->factory()->home_object_symbol();
993     case kBoolean:
994       return isolate->factory()->ToBoolean(boolean_);
995     case kNull:
996       return isolate->factory()->null_value();
997     case kUndefined:
998       return isolate->factory()->undefined_value();
999     case kTheHole:
1000       return isolate->factory()->the_hole_value();
1001     case kBigInt:
1002       // This should never fail: the parser will never create a BigInt
1003       // literal that cannot be allocated.
1004       return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
1005   }
1006   UNREACHABLE();
1007 }
1008 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
1009     Handle<Object> Literal::BuildValue(Isolate* isolate) const;
1010 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
1011     Handle<Object> Literal::BuildValue(OffThreadIsolate* isolate) const;
1012 
ToBooleanIsTrue() const1013 bool Literal::ToBooleanIsTrue() const {
1014   switch (type()) {
1015     case kSmi:
1016       return smi_ != 0;
1017     case kHeapNumber:
1018       return DoubleToBoolean(number_);
1019     case kString:
1020       return !string_->IsEmpty();
1021     case kNull:
1022     case kUndefined:
1023       return false;
1024     case kBoolean:
1025       return boolean_;
1026     case kBigInt: {
1027       const char* bigint_str = bigint_.c_str();
1028       size_t length = strlen(bigint_str);
1029       DCHECK_GT(length, 0);
1030       if (length == 1 && bigint_str[0] == '0') return false;
1031       // Skip over any radix prefix; BigInts with length > 1 only
1032       // begin with zero if they include a radix.
1033       for (size_t i = (bigint_str[0] == '0') ? 2 : 0; i < length; ++i) {
1034         if (bigint_str[i] != '0') return true;
1035       }
1036       return false;
1037     }
1038     case kSymbol:
1039       return true;
1040     case kTheHole:
1041       UNREACHABLE();
1042   }
1043   UNREACHABLE();
1044 }
1045 
Hash()1046 uint32_t Literal::Hash() {
1047   return IsString() ? AsRawString()->Hash()
1048                     : ComputeLongHash(double_to_uint64(AsNumber()));
1049 }
1050 
1051 // static
Match(void * a,void * b)1052 bool Literal::Match(void* a, void* b) {
1053   Literal* x = static_cast<Literal*>(a);
1054   Literal* y = static_cast<Literal*>(b);
1055   return (x->IsString() && y->IsString() &&
1056           x->AsRawString() == y->AsRawString()) ||
1057          (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
1058 }
1059 
NewNumberLiteral(double number,int pos)1060 Literal* AstNodeFactory::NewNumberLiteral(double number, int pos) {
1061   int int_value;
1062   if (DoubleToSmiInteger(number, &int_value)) {
1063     return NewSmiLiteral(int_value, pos);
1064   }
1065   return new (zone_) Literal(number, pos);
1066 }
1067 
debug_name()1068 const char* CallRuntime::debug_name() {
1069 #ifdef DEBUG
1070   return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
1071                         : function_->name;
1072 #else
1073   return is_jsruntime() ? "(context function)" : function_->name;
1074 #endif  // DEBUG
1075 }
1076 
1077 }  // namespace internal
1078 }  // namespace v8
1079