ast.cc 32 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// 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"
lpy's avatar
lpy committed
12
#include "src/base/hashmap.h"
13
#include "src/builtins/builtins-constructor.h"
14
#include "src/builtins/builtins.h"
15 16
#include "src/numbers/conversions-inl.h"
#include "src/numbers/double.h"
17
#include "src/objects/contexts.h"
18
#include "src/objects/elements.h"
19
#include "src/objects/literal-objects-inl.h"
20
#include "src/objects/literal-objects.h"
21
#include "src/objects/map.h"
22
#include "src/objects/objects-inl.h"
23 24
#include "src/objects/property-details.h"
#include "src/objects/property.h"
25
#include "src/strings/string-stream.h"
26
#include "src/zone/zone-list-inl.h"
27

28 29
namespace v8 {
namespace internal {
30 31 32 33

// ----------------------------------------------------------------------------
// Implementation of other node functionality.

34 35
#ifdef DEBUG

36 37 38 39 40 41 42
static const char* NameForNativeContextIntrinsicIndex(uint32_t idx) {
  switch (idx) {
#define NATIVE_CONTEXT_FIELDS_IDX(NAME, Type, name) \
  case Context::NAME:                               \
    return #name;

    NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELDS_IDX)
43
#undef NATIVE_CONTEXT_FIELDS_IDX
44 45 46 47 48 49 50 51

    default:
      break;
  }

  return "UnknownIntrinsicIndex";
}

52
void AstNode::Print(Isolate* isolate) {
53
  AllowHandleDereference allow_deref;
54 55 56 57 58 59
  AstPrinter::PrintOut(isolate, this);
}


#endif  // DEBUG

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
#define RETURN_NODE(Node) \
  case k##Node:           \
    return static_cast<Node*>(this);

IterationStatement* AstNode::AsIterationStatement() {
  switch (node_type()) {
    ITERATION_NODE_LIST(RETURN_NODE);
    default:
      return nullptr;
  }
}

MaterializedLiteral* AstNode::AsMaterializedLiteral() {
  switch (node_type()) {
    LITERAL_NODE_LIST(RETURN_NODE);
    default:
      return nullptr;
  }
}

#undef RETURN_NODE

82
bool Expression::IsSmiLiteral() const {
83
  return IsLiteral() && AsLiteral()->type() == Literal::kSmi;
84 85
}

86
bool Expression::IsNumberLiteral() const {
87
  return IsLiteral() && AsLiteral()->IsNumber();
88 89
}

90
bool Expression::IsStringLiteral() const {
91
  return IsLiteral() && AsLiteral()->type() == Literal::kString;
92 93
}

94 95
bool Expression::IsPropertyName() const {
  return IsLiteral() && AsLiteral()->IsPropertyName();
96
}
97

98
bool Expression::IsNullLiteral() const {
99
  return IsLiteral() && AsLiteral()->type() == Literal::kNull;
100 101 102
}

bool Expression::IsTheHoleLiteral() const {
103
  return IsLiteral() && AsLiteral()->type() == Literal::kTheHole;
104 105
}

106 107 108 109 110 111 112
bool Expression::IsCompileTimeValue() {
  if (IsLiteral()) return true;
  MaterializedLiteral* literal = AsMaterializedLiteral();
  if (literal == nullptr) return false;
  return literal->IsSimple();
}

113
bool Expression::IsUndefinedLiteral() const {
114
  if (IsLiteral() && AsLiteral()->type() == Literal::kUndefined) return true;
115

116
  const VariableProxy* var_proxy = AsVariableProxy();
117
  if (var_proxy == nullptr) return false;
118 119 120
  Variable* var = var_proxy->var();
  // The global identifier "undefined" is immutable. Everything
  // else could be reassigned.
121
  return var != nullptr && var->IsUnallocated() &&
122
         var_proxy->raw_name()->IsOneByteEqualTo("undefined");
123 124
}

125 126 127 128
bool Expression::IsLiteralButNotNullOrUndefined() const {
  return IsLiteral() && !IsNullOrUndefinedLiteral();
}

129 130 131 132 133 134 135 136
bool Expression::ToBooleanIsTrue() const {
  return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
}

bool Expression::ToBooleanIsFalse() const {
  return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
}

137 138 139 140
bool Expression::IsPrivateName() const {
  return IsVariableProxy() && AsVariableProxy()->IsPrivateName();
}

141 142 143 144
bool Expression::IsValidReferenceExpression() const {
  return IsProperty() ||
         (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
}
145

146 147 148
bool Expression::IsAnonymousFunctionDefinition() const {
  return (IsFunctionLiteral() &&
          AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
149 150
         (IsClassLiteral() &&
          AsClassLiteral()->IsAnonymousFunctionDefinition());
151 152
}

153 154 155 156 157 158 159 160
bool Expression::IsConciseMethodDefinition() const {
  return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
}

bool Expression::IsAccessorFunctionDefinition() const {
  return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
}

161
VariableProxy::VariableProxy(Variable* var, int start_position)
162
    : Expression(start_position, kVariableProxy),
163 164
      raw_name_(var->raw_name()),
      next_unresolved_(nullptr) {
165 166
  DCHECK(!var->is_this());
  bit_field_ |= IsAssignedField::encode(false) |
167 168
                IsResolvedField::encode(false) |
                HoleCheckModeField::encode(HoleCheckMode::kElided);
169 170 171
  BindTo(var);
}

172 173
VariableProxy::VariableProxy(const VariableProxy* copy_from)
    : Expression(copy_from->position(), kVariableProxy),
174
      next_unresolved_(nullptr) {
175
  bit_field_ = copy_from->bit_field_;
176 177
  DCHECK(!copy_from->is_resolved());
  raw_name_ = copy_from->raw_name_;
178 179
}

180
void VariableProxy::BindTo(Variable* var) {
181
  DCHECK_EQ(raw_name(), var->raw_name());
182 183
  set_var(var);
  set_is_resolved();
184
  var->set_is_used();
185
  if (is_assigned()) var->SetMaybeAssigned();
186 187
}

188 189 190
Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
                       Expression* value, int pos)
    : Expression(pos, node_type), target_(target), value_(value) {
191
  bit_field_ |= TokenField::encode(op);
192
}
193

194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
void FunctionLiteral::set_inferred_name(Handle<String> inferred_name) {
  DCHECK(!inferred_name.is_null());
  inferred_name_ = inferred_name;
  DCHECK(raw_inferred_name_ == nullptr || raw_inferred_name_->IsEmpty());
  raw_inferred_name_ = nullptr;
  scope()->set_has_inferred_function_name(true);
}

void FunctionLiteral::set_raw_inferred_name(
    const AstConsString* raw_inferred_name) {
  DCHECK_NOT_NULL(raw_inferred_name);
  raw_inferred_name_ = raw_inferred_name;
  DCHECK(inferred_name_.is_null());
  inferred_name_ = Handle<String>();
  scope()->set_has_inferred_function_name(true);
}

211 212 213 214 215
bool FunctionLiteral::ShouldEagerCompile() const {
  return scope()->ShouldEagerCompile();
}

void FunctionLiteral::SetShouldEagerCompile() {
216
  scope()->set_should_eager_compile();
217
}
218 219 220 221 222

bool FunctionLiteral::AllowsLazyCompilation() {
  return scope()->AllowsLazyCompilation();
}

223
bool FunctionLiteral::SafeToSkipArgumentsAdaptor() const {
224
  return language_mode() == LanguageMode::kStrict &&
225 226 227 228
         scope()->arguments() == nullptr &&
         scope()->rest_parameter() == nullptr;
}

229 230 231
Handle<String> FunctionLiteral::name(Isolate* isolate) const {
  return raw_name_ ? raw_name_->string() : isolate->factory()->empty_string();
}
232

233 234 235 236 237 238 239 240 241 242
int FunctionLiteral::start_position() const {
  return scope()->start_position();
}


int FunctionLiteral::end_position() const {
  return scope()->end_position();
}


243 244
LanguageMode FunctionLiteral::language_mode() const {
  return scope()->language_mode();
245 246
}

247
FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
248

249 250 251 252
bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
  if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
  DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
  return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
253 254
}

255 256 257 258 259 260 261 262 263 264
std::unique_ptr<char[]> FunctionLiteral::GetDebugName() const {
  const AstConsString* cons_string;
  if (raw_name_ != nullptr && !raw_name_->IsEmpty()) {
    cons_string = raw_name_;
  } else if (raw_inferred_name_ != nullptr && !raw_inferred_name_->IsEmpty()) {
    cons_string = raw_inferred_name_;
  } else if (!inferred_name_.is_null()) {
    AllowHandleDereference allow_deref;
    return inferred_name_->ToCString();
  } else {
265 266 267
    char* empty_str = new char[1];
    empty_str[0] = 0;
    return std::unique_ptr<char[]>(empty_str);
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
  }

  // TODO(rmcilroy): Deal with two-character strings.
  std::vector<char> result_vec;
  std::forward_list<const AstRawString*> strings = cons_string->ToRawStrings();
  for (const AstRawString* string : strings) {
    if (!string->is_one_byte()) break;
    for (int i = 0; i < string->length(); i++) {
      result_vec.push_back(string->raw_data()[i]);
    }
  }
  std::unique_ptr<char[]> result(new char[result_vec.size() + 1]);
  memcpy(result.get(), result_vec.data(), result_vec.size());
  result[result_vec.size()] = '\0';
  return result;
}

285 286 287 288 289 290 291 292 293 294 295
bool FunctionLiteral::requires_brand_initialization() const {
  Scope* outer = scope_->outer_scope();

  // If there are no variables declared in the outer scope other than
  // the class name variable, the outer class scope may be elided when
  // the function is deserialized after preparsing.
  if (!outer->is_class_scope()) return false;

  return outer->AsClassScope()->brand() != nullptr;
}

296
ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
297 298
                                             Kind kind, bool is_computed_name)
    : LiteralProperty(key, value, is_computed_name),
299
      kind_(kind),
300
      emit_store_(true) {}
301 302

ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
arv's avatar
arv committed
303 304
                                             Expression* key, Expression* value,
                                             bool is_computed_name)
305
    : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
306 307
  if (!is_computed_name && key->AsLiteral()->IsString() &&
      key->AsLiteral()->AsRawString() == ast_value_factory->proto_string()) {
308
    kind_ = PROTOTYPE;
309
  } else if (value_->AsMaterializedLiteral() != nullptr) {
310
    kind_ = MATERIALIZED_LITERAL;
311
  } else if (value_->IsLiteral()) {
312
    kind_ = CONSTANT;
313
  } else {
314
    kind_ = COMPUTED;
315 316 317
  }
}

318
bool LiteralProperty::NeedsSetFunctionName() const {
319 320 321
  return is_computed_name() && (value_->IsAnonymousFunctionDefinition() ||
                                value_->IsConciseMethodDefinition() ||
                                value_->IsAccessorFunctionDefinition());
322
}
323

324 325
ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
                                           Kind kind, bool is_static,
326 327
                                           bool is_computed_name,
                                           bool is_private)
328 329
    : LiteralProperty(key, value, is_computed_name),
      kind_(kind),
330
      is_static_(is_static),
331
      is_private_(is_private),
332
      private_or_computed_name_var_(nullptr) {}
333 334

bool ObjectLiteral::Property::IsCompileTimeValue() const {
335
  return kind_ == CONSTANT ||
336
         (kind_ == MATERIALIZED_LITERAL && value_->IsCompileTimeValue());
337 338 339
}


340 341 342 343
void ObjectLiteral::Property::set_emit_store(bool emit_store) {
  emit_store_ = emit_store;
}

344
bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
345

346
void ObjectLiteral::CalculateEmitStore(Zone* zone) {
347 348 349
  const auto GETTER = ObjectLiteral::Property::GETTER;
  const auto SETTER = ObjectLiteral::Property::SETTER;

350 351
  ZoneAllocationPolicy allocator(zone);

352 353
  CustomMatcherZoneHashMap table(
      Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
354 355
  for (int i = properties()->length() - 1; i >= 0; i--) {
    ObjectLiteral::Property* property = properties()->at(i);
arv's avatar
arv committed
356
    if (property->is_computed_name()) continue;
357
    if (property->IsPrototype()) continue;
arv's avatar
arv committed
358
    Literal* literal = property->key()->AsLiteral();
359
    DCHECK(!literal->IsNullLiteral());
360

361
    uint32_t hash = literal->Hash();
362
    ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
    if (entry->value == nullptr) {
      entry->value = property;
    } else {
      // We already have a later definition of this property, so we don't need
      // to emit a store for the current one.
      //
      // There are two subtleties here.
      //
      // (1) Emitting a store might actually be incorrect. For example, in {get
      // foo() {}, foo: 42}, the getter store would override the data property
      // (which, being a non-computed compile-time valued property, is already
      // part of the initial literal object.
      //
      // (2) If the later definition is an accessor (say, a getter), and the
      // current definition is a complementary accessor (here, a setter), then
      // we still must emit a store for the current definition.

      auto later_kind =
381
          static_cast<ObjectLiteral::Property*>(entry->value)->kind();
382 383 384 385
      bool complementary_accessors =
          (property->kind() == GETTER && later_kind == SETTER) ||
          (property->kind() == SETTER && later_kind == GETTER);
      if (!complementary_accessors) {
386
        property->set_emit_store(false);
387 388 389
        if (later_kind == GETTER || later_kind == SETTER) {
          entry->value = property;
        }
390
      }
391 392 393 394
    }
  }
}

395 396 397 398 399 400 401 402
void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
  // We still check for __proto__:null after computed property names.
  for (; i < properties()->length(); i++) {
    if (properties()->at(i)->IsNullPrototype()) {
      set_has_null_protoype(true);
      break;
    }
  }
403 404
}

405 406
int ObjectLiteral::InitDepthAndFlags() {
  if (is_initialized()) return depth();
407
  bool is_simple = true;
408
  bool has_seen_prototype = false;
409
  bool needs_initial_allocation_site = false;
410
  int depth_acc = 1;
411
  uint32_t nof_properties = 0;
412
  uint32_t elements = 0;
413
  uint32_t max_element_index = 0;
414 415
  for (int i = 0; i < properties()->length(); i++) {
    ObjectLiteral::Property* property = properties()->at(i);
416 417 418 419 420 421 422 423 424
    if (property->IsPrototype()) {
      has_seen_prototype = true;
      // __proto__:null has no side-effects and is set directly on the
      // boilerplate.
      if (property->IsNullPrototype()) {
        set_has_null_protoype(true);
        continue;
      }
      DCHECK(!has_null_prototype());
425 426 427
      is_simple = false;
      continue;
    }
428
    if (nof_properties == boilerplate_properties_) {
arv's avatar
arv committed
429
      DCHECK(property->is_computed_name());
430
      is_simple = false;
431
      if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
arv's avatar
arv committed
432 433 434 435
      break;
    }
    DCHECK(!property->is_computed_name());

436 437 438 439 440
    MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
    if (literal != nullptr) {
      int subliteral_depth = literal->InitDepthAndFlags() + 1;
      if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
      needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
441 442
    }

443
    Literal* key = property->key()->AsLiteral();
444 445
    Expression* value = property->value();

446
    bool is_compile_time_value = value->IsCompileTimeValue();
447
    is_simple = is_simple && is_compile_time_value;
448 449 450 451 452 453

    // Keep track of the number of elements in the object literal and
    // the largest element index.  If the largest element index is
    // much larger than the number of elements, creating an object
    // literal with fast elements will be a waste of space.
    uint32_t element_index = 0;
454
    if (key->AsArrayIndex(&element_index)) {
455
      max_element_index = Max(element_index, max_element_index);
456
      elements++;
457 458
    } else {
      DCHECK(key->IsPropertyName());
459 460
    }

461
    nof_properties++;
462 463
  }

464 465 466 467
  set_depth(depth_acc);
  set_is_simple(is_simple);
  set_needs_initial_allocation_site(needs_initial_allocation_site);
  set_has_elements(elements > 0);
468 469
  set_fast_elements((max_element_index <= 32) ||
                    ((2 * elements) >= max_element_index));
470
  return depth_acc;
471 472
}

473 474
void ObjectLiteral::BuildBoilerplateDescription(Isolate* isolate) {
  if (!boilerplate_description_.is_null()) return;
475

476
  int index_keys = 0;
477
  bool has_seen_proto = false;
478 479
  for (int i = 0; i < properties()->length(); i++) {
    ObjectLiteral::Property* property = properties()->at(i);
480
    if (property->IsPrototype()) {
481 482 483
      has_seen_proto = true;
      continue;
    }
484
    if (property->is_computed_name()) continue;
485

486
    Literal* key = property->key()->AsLiteral();
487
    if (!key->IsPropertyName()) index_keys++;
488 489
  }

490 491 492 493
  Handle<ObjectBoilerplateDescription> boilerplate_description =
      isolate->factory()->NewObjectBoilerplateDescription(
          boilerplate_properties_, properties()->length(), index_keys,
          has_seen_proto);
494 495 496 497

  int position = 0;
  for (int i = 0; i < properties()->length(); i++) {
    ObjectLiteral::Property* property = properties()->at(i);
498
    if (property->IsPrototype()) continue;
499

500
    if (static_cast<uint32_t>(position) == boilerplate_properties_) {
501 502 503 504 505 506
      DCHECK(property->is_computed_name());
      break;
    }
    DCHECK(!property->is_computed_name());

    MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
507
    if (m_literal != nullptr) {
508 509 510 511 512 513
      m_literal->BuildConstants(isolate);
    }

    // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
    // value for COMPUTED properties, the real value is filled in at
    // runtime. The enumeration order is maintained.
514
    Literal* key_literal = property->key()->AsLiteral();
515
    uint32_t element_index = 0;
516 517 518 519 520 521
    Handle<Object> key =
        key_literal->AsArrayIndex(&element_index)
            ? isolate->factory()->NewNumberFromUint(element_index)
            : Handle<Object>::cast(key_literal->AsRawPropertyName()->string());

    Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
522 523

    // Add name, value pair to the fixed array.
524
    boilerplate_description->set_key_value(position++, *key, *value);
525 526
  }

527 528 529
  boilerplate_description->set_flags(EncodeLiteralType());

  boilerplate_description_ = boilerplate_description;
530 531
}

532
bool ObjectLiteral::IsFastCloningSupported() const {
533
  // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
534
  // literals don't support copy-on-write (COW) elements for now.
535
  // TODO(mvstanton): make object literals support COW elements.
536
  return fast_elements() && is_shallow() &&
537 538
         properties_count() <=
             ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
539
}
540

541 542
int ArrayLiteral::InitDepthAndFlags() {
  if (is_initialized()) return depth();
543

544 545
  int constants_length =
      first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
546 547

  // Fill in the literals.
548
  bool is_simple = first_spread_index_ < 0;
549 550 551 552
  int depth_acc = 1;
  int array_index = 0;
  for (; array_index < constants_length; array_index++) {
    Expression* element = values()->at(array_index);
553
    MaterializedLiteral* literal = element->AsMaterializedLiteral();
554
    if (literal != nullptr) {
555 556
      int subliteral_depth = literal->InitDepthAndFlags() + 1;
      if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
557 558
    }

559
    if (!element->IsCompileTimeValue()) {
560 561 562 563 564
      is_simple = false;
    }
  }

  set_depth(depth_acc);
565 566 567 568 569
  set_is_simple(is_simple);
  // Array literals always need an initial allocation site to properly track
  // elements transitions.
  set_needs_initial_allocation_site(true);
  return depth_acc;
570 571
}

572 573
void ArrayLiteral::BuildBoilerplateDescription(Isolate* isolate) {
  if (!boilerplate_description_.is_null()) return;
574

575 576
  int constants_length =
      first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
577 578 579
  ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
  Handle<FixedArray> fixed_array =
      isolate->factory()->NewFixedArrayWithHoles(constants_length);
580 581 582

  // Fill in the literals.
  bool is_holey = false;
arv's avatar
arv committed
583
  int array_index = 0;
584
  for (; array_index < constants_length; array_index++) {
arv's avatar
arv committed
585
    Expression* element = values()->at(array_index);
586
    DCHECK(!element->IsSpread());
587
    MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
588
    if (m_literal != nullptr) {
589
      m_literal->BuildConstants(isolate);
590
    }
591

592 593 594
    // New handle scope here, needs to be after BuildContants().
    HandleScope scope(isolate);
    Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
595
    if (boilerplate_value->IsTheHole(isolate)) {
596
      is_holey = true;
597 598 599
      continue;
    }

600
    if (boilerplate_value->IsUninitialized(isolate)) {
601
      boilerplate_value = handle(Smi::kZero, isolate);
602
    }
603

604 605
    kind = GetMoreGeneralElementsKind(
        kind, boilerplate_value->OptimalElementsKind(isolate));
606
    fixed_array->set(array_index, *boilerplate_value);
607 608
  }

609
  if (is_holey) kind = GetHoleyElementsKind(kind);
610 611 612

  // Simple and shallow arrays can be lazily copied, we transform the
  // elements array to a copy-on-write array.
613
  if (is_simple() && depth() == 1 && array_index > 0 &&
614
      IsSmiOrObjectElementsKind(kind)) {
615
    fixed_array->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
616 617 618
  }

  Handle<FixedArrayBase> elements = fixed_array;
619
  if (IsDoubleElementsKind(kind)) {
620 621 622 623
    ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
    elements = isolate->factory()->NewFixedDoubleArray(constants_length);
    // We are copying from non-fast-double to fast-double.
    ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
624 625
    accessor->CopyElements(isolate, fixed_array, from_kind, elements,
                           constants_length);
626 627
  }

628 629
  boilerplate_description_ =
      isolate->factory()->NewArrayBoilerplateDescription(kind, elements);
630 631
}

632 633
bool ArrayLiteral::IsFastCloningSupported() const {
  return depth() <= 1 &&
634
         values_.length() <=
635
             ConstructorBuiltins::kMaximumClonedShallowArrayElements;
636
}
637

638 639 640 641 642 643
bool MaterializedLiteral::IsSimple() const {
  if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
  if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
  DCHECK(IsRegExpLiteral());
  return false;
}
644

645 646
Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
                                                        Isolate* isolate) {
647
  if (expression->IsLiteral()) {
648
    return expression->AsLiteral()->BuildValue(isolate);
649
  }
650
  if (expression->IsCompileTimeValue()) {
651 652 653 654 655 656 657 658 659 660
    if (expression->IsObjectLiteral()) {
      ObjectLiteral* object_literal = expression->AsObjectLiteral();
      DCHECK(object_literal->is_simple());
      return object_literal->boilerplate_description();
    } else {
      DCHECK(expression->IsArrayLiteral());
      ArrayLiteral* array_literal = expression->AsArrayLiteral();
      DCHECK(array_literal->is_simple());
      return array_literal->boilerplate_description();
    }
661 662 663 664
  }
  return isolate->factory()->uninitialized_value();
}

665 666 667 668 669 670 671 672
int MaterializedLiteral::InitDepthAndFlags() {
  if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
  if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
  DCHECK(IsRegExpLiteral());
  return 1;
}

bool MaterializedLiteral::NeedsInitialAllocationSite() {
673
  if (IsArrayLiteral()) {
674
    return AsArrayLiteral()->needs_initial_allocation_site();
675 676
  }
  if (IsObjectLiteral()) {
677
    return AsObjectLiteral()->needs_initial_allocation_site();
678 679
  }
  DCHECK(IsRegExpLiteral());
680
  return false;
681
}
682

683
void MaterializedLiteral::BuildConstants(Isolate* isolate) {
684
  if (IsArrayLiteral()) {
685 686
    AsArrayLiteral()->BuildBoilerplateDescription(isolate);
    return;
687 688
  }
  if (IsObjectLiteral()) {
689 690
    AsObjectLiteral()->BuildBoilerplateDescription(isolate);
    return;
691
  }
692
  DCHECK(IsRegExpLiteral());
693 694
}

695 696
Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
    Isolate* isolate) {
697 698
  Handle<FixedArray> raw_strings = isolate->factory()->NewFixedArray(
      this->raw_strings()->length(), AllocationType::kOld);
699 700
  bool raw_and_cooked_match = true;
  for (int i = 0; i < raw_strings->length(); ++i) {
701 702 703
    if (this->cooked_strings()->at(i) == nullptr ||
        *this->raw_strings()->at(i)->string() !=
            *this->cooked_strings()->at(i)->string()) {
704 705
      raw_and_cooked_match = false;
    }
706
    raw_strings->set(i, *this->raw_strings()->at(i)->string());
707 708 709 710
  }
  Handle<FixedArray> cooked_strings = raw_strings;
  if (!raw_and_cooked_match) {
    cooked_strings = isolate->factory()->NewFixedArray(
711
        this->cooked_strings()->length(), AllocationType::kOld);
712
    for (int i = 0; i < cooked_strings->length(); ++i) {
713 714 715
      if (this->cooked_strings()->at(i) != nullptr) {
        cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
      } else {
716
        cooked_strings->set(i, ReadOnlyRoots(isolate).undefined_value());
717
      }
718 719
    }
  }
720 721
  return isolate->factory()->NewTemplateObjectDescription(raw_strings,
                                                          cooked_strings);
722 723
}

724 725 726 727 728 729 730 731
static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
  // Add is not commutative due to potential for string addition.
  return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
         op == Token::BIT_XOR;
}

// Check for the pattern: x + 1.
static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
732
                                     Expression** expr, Smi* literal) {
733 734 735 736 737 738 739 740 741
  if (right->IsSmiLiteral()) {
    *expr = left;
    *literal = right->AsLiteral()->AsSmiLiteral();
    return true;
  }
  return false;
}

bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
742
                                            Smi* literal) {
743 744 745 746 747
  return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
         (IsCommutativeOperationWithSmiLiteral(op()) &&
          MatchSmiLiteralOperation(right_, left_, subexpr, literal));
}

748 749
static bool IsTypeof(Expression* expr) {
  UnaryOperation* maybe_unary = expr->AsUnaryOperation();
750
  return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
751 752 753
}

// Check for the pattern: typeof <expression> equals <string literal>.
754 755 756
static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
                                      Expression* right, Expression** expr,
                                      Literal** literal) {
757
  if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
758
    *expr = left->AsUnaryOperation()->expression();
759
    *literal = right->AsLiteral();
760 761 762 763 764
    return true;
  }
  return false;
}

765
bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
766 767 768
                                              Literal** literal) {
  return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
         MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
769
}
770 771


772 773
static bool IsVoidOfLiteral(Expression* expr) {
  UnaryOperation* maybe_unary = expr->AsUnaryOperation();
774 775
  return maybe_unary != nullptr && maybe_unary->op() == Token::VOID &&
         maybe_unary->expression()->IsLiteral();
776 777
}

778

779 780
// Check for the pattern: void <literal> equals <expression> or
// undefined equals <expression>
781 782 783
static bool MatchLiteralCompareUndefined(Expression* left,
                                         Token::Value op,
                                         Expression* right,
784
                                         Expression** expr) {
785
  if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
786 787 788
    *expr = right;
    return true;
  }
789
  if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
790
    *expr = right;
791 792 793 794 795
    return true;
  }
  return false;
}

796
bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
797 798
  return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
         MatchLiteralCompareUndefined(right_, op(), left_, expr);
799
}
800

801 802 803 804 805 806 807
// Check for the pattern: null equals <expression>
static bool MatchLiteralCompareNull(Expression* left,
                                    Token::Value op,
                                    Expression* right,
                                    Expression** expr) {
  if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
    *expr = right;
808 809 810 811 812
    return true;
  }
  return false;
}

813
bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
814 815
  return MatchLiteralCompareNull(left_, op(), right_, expr) ||
         MatchLiteralCompareNull(right_, op(), left_, expr);
816 817
}

818
Call::CallType Call::GetCallType() const {
819
  VariableProxy* proxy = expression()->AsVariableProxy();
820
  if (proxy != nullptr) {
821
    if (proxy->var()->IsUnallocated()) {
822 823
      return GLOBAL_CALL;
    } else if (proxy->var()->IsLookupSlot()) {
824 825 826 827
      // Calls going through 'with' always use VariableMode::kDynamic rather
      // than VariableMode::kDynamicLocal or VariableMode::kDynamicGlobal.
      return proxy->var()->mode() == VariableMode::kDynamic ? WITH_CALL
                                                            : OTHER_CALL;
828 829 830
    }
  }

831
  if (expression()->IsSuperCallReference()) return SUPER_CALL;
832

833
  Property* property = expression()->AsProperty();
834
  if (property != nullptr) {
835 836 837
    if (property->IsPrivateReference()) {
      return PRIVATE_CALL;
    }
838
    bool is_super = property->IsSuperAccess();
839
    if (property->key()->IsPropertyName()) {
840 841 842 843 844 845
      return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
    } else {
      return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
    }
  }

846 847 848 849
  if (expression()->IsResolvedProperty()) {
    return RESOLVED_PROPERTY_CALL;
  }

850
  return OTHER_CALL;
851 852
}

853
CaseClause::CaseClause(Zone* zone, Expression* label,
854 855
                       const ScopedPtrList<Statement>& statements)
    : label_(label), statements_(0, nullptr) {
856
  statements.CopyTo(&statements_, zone);
857
}
858

859 860 861 862 863 864
bool Literal::IsPropertyName() const {
  if (type() != kString) return false;
  uint32_t index;
  return !string_->AsArrayIndex(&index);
}

865
bool Literal::ToUint32(uint32_t* value) const {
866
  switch (type()) {
867 868
    case kString:
      return string_->AsArrayIndex(value);
869 870 871 872 873 874 875 876
    case kSmi:
      if (smi_ < 0) return false;
      *value = static_cast<uint32_t>(smi_);
      return true;
    case kHeapNumber:
      return DoubleToUint32IfEqualToSelf(AsNumber(), value);
    default:
      return false;
877 878 879
  }
}

880
bool Literal::AsArrayIndex(uint32_t* value) const {
881 882 883
  return ToUint32(value) && *value != kMaxUInt32;
}

884 885 886 887 888
Handle<Object> Literal::BuildValue(Isolate* isolate) const {
  switch (type()) {
    case kSmi:
      return handle(Smi::FromInt(smi_), isolate);
    case kHeapNumber:
889
      return isolate->factory()->NewNumber(number_, AllocationType::kOld);
890 891 892 893
    case kString:
      return string_->string();
    case kSymbol:
      return isolate->factory()->home_object_symbol();
894 895
    case kBoolean:
      return isolate->factory()->ToBoolean(boolean_);
896 897 898 899 900 901 902
    case kNull:
      return isolate->factory()->null_value();
    case kUndefined:
      return isolate->factory()->undefined_value();
    case kTheHole:
      return isolate->factory()->the_hole_value();
    case kBigInt:
903 904
      // This should never fail: the parser will never create a BigInt
      // literal that cannot be allocated.
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
      return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
  }
  UNREACHABLE();
}

bool Literal::ToBooleanIsTrue() const {
  switch (type()) {
    case kSmi:
      return smi_ != 0;
    case kHeapNumber:
      return DoubleToBoolean(number_);
    case kString:
      return !string_->IsEmpty();
    case kNull:
    case kUndefined:
      return false;
921 922
    case kBoolean:
      return boolean_;
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
    case kBigInt: {
      const char* bigint_str = bigint_.c_str();
      size_t length = strlen(bigint_str);
      DCHECK_GT(length, 0);
      if (length == 1 && bigint_str[0] == '0') return false;
      // Skip over any radix prefix; BigInts with length > 1 only
      // begin with zero if they include a radix.
      for (size_t i = (bigint_str[0] == '0') ? 2 : 0; i < length; ++i) {
        if (bigint_str[i] != '0') return true;
      }
      return false;
    }
    case kSymbol:
      return true;
    case kTheHole:
      UNREACHABLE();
  }
  UNREACHABLE();
}

943
uint32_t Literal::Hash() {
944 945
  return IsString() ? AsRawString()->Hash()
                    : ComputeLongHash(double_to_uint64(AsNumber()));
946 947 948 949
}


// static
950 951 952 953 954
bool Literal::Match(void* a, void* b) {
  Literal* x = static_cast<Literal*>(a);
  Literal* y = static_cast<Literal*>(b);
  return (x->IsString() && y->IsString() &&
          x->AsRawString() == y->AsRawString()) ||
955
         (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
956 957
}

958 959 960 961 962 963 964 965
Literal* AstNodeFactory::NewNumberLiteral(double number, int pos) {
  int int_value;
  if (DoubleToSmiInteger(number, &int_value)) {
    return NewSmiLiteral(int_value, pos);
  }
  return new (zone_) Literal(number, pos);
}

966 967
const char* CallRuntime::debug_name() {
#ifdef DEBUG
968 969
  return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
                        : function_->name;
970 971 972 973 974
#else
  return is_jsruntime() ? "(context function)" : function_->name;
#endif  // DEBUG
}

975 976 977 978
#define RETURN_LABELS(NodeType) \
  case k##NodeType:             \
    return static_cast<const NodeType*>(this)->labels();

979
ZonePtrList<const AstRawString>* BreakableStatement::labels() const {
980 981 982 983 984 985 986 987 988 989
  switch (node_type()) {
    BREAKABLE_NODE_LIST(RETURN_LABELS)
    ITERATION_NODE_LIST(RETURN_LABELS)
    default:
      UNREACHABLE();
  }
}

#undef RETURN_LABELS

990 991
}  // namespace internal
}  // namespace v8