ast.cc 30.1 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/compile-time-value.h"
11
#include "src/ast/prettyprinter.h"
12
#include "src/ast/scopes.h"
lpy's avatar
lpy committed
13
#include "src/base/hashmap.h"
14
#include "src/builtins/builtins-constructor.h"
15
#include "src/builtins/builtins.h"
16 17
#include "src/code-stubs.h"
#include "src/contexts.h"
18
#include "src/conversions-inl.h"
19
#include "src/double.h"
20
#include "src/elements.h"
21
#include "src/objects-inl.h"
22
#include "src/objects/literal-objects.h"
23
#include "src/objects/map.h"
24
#include "src/property-details.h"
lpy's avatar
lpy committed
25
#include "src/property.h"
26
#include "src/string-stream.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 53
void AstNode::Print() { Print(Isolate::Current()); }

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


#endif  // DEBUG

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
#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;
  }
}

BreakableStatement* AstNode::AsBreakableStatement() {
  switch (node_type()) {
    BREAKABLE_NODE_LIST(RETURN_NODE);
    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

93
bool Expression::IsSmiLiteral() const {
94
  return IsLiteral() && AsLiteral()->type() == Literal::kSmi;
95 96
}

97
bool Expression::IsNumberLiteral() const {
98
  return IsLiteral() && AsLiteral()->IsNumber();
99 100
}

101
bool Expression::IsStringLiteral() const {
102
  return IsLiteral() && AsLiteral()->type() == Literal::kString;
103 104
}

105 106
bool Expression::IsPropertyName() const {
  return IsLiteral() && AsLiteral()->IsPropertyName();
107
}
108

109
bool Expression::IsNullLiteral() const {
110
  return IsLiteral() && AsLiteral()->type() == Literal::kNull;
111 112 113
}

bool Expression::IsTheHoleLiteral() const {
114
  return IsLiteral() && AsLiteral()->type() == Literal::kTheHole;
115 116
}

117
bool Expression::IsUndefinedLiteral() const {
118
  if (IsLiteral() && AsLiteral()->type() == Literal::kUndefined) return true;
119

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

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

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

bool Expression::IsValidReferenceExpression() const {
138 139 140 141
  // We don't want expressions wrapped inside RewritableExpression to be
  // considered as valid reference expressions, as they will be rewritten
  // to something (most probably involving a do expression).
  if (IsRewritableExpression()) return false;
142 143 144
  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 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
bool Statement::IsJump() const {
  switch (node_type()) {
#define JUMP_NODE_LIST(V) \
  V(Block)                \
  V(ExpressionStatement)  \
  V(ContinueStatement)    \
  V(BreakStatement)       \
  V(ReturnStatement)      \
  V(IfStatement)
#define GENERATE_CASE(Node) \
  case k##Node:             \
    return static_cast<const Node*>(this)->IsJump();
    JUMP_NODE_LIST(GENERATE_CASE)
#undef GENERATE_CASE
#undef JUMP_NODE_LIST
    default:
      return false;
  }
}
180

181
VariableProxy::VariableProxy(Variable* var, int start_position)
182
    : Expression(start_position, kVariableProxy),
183 184
      raw_name_(var->raw_name()),
      next_unresolved_(nullptr) {
185 186 187 188
  bit_field_ |= IsThisField::encode(var->is_this()) |
                IsAssignedField::encode(false) |
                IsResolvedField::encode(false) |
                HoleCheckModeField::encode(HoleCheckMode::kElided);
189 190 191
  BindTo(var);
}

192 193
VariableProxy::VariableProxy(const VariableProxy* copy_from)
    : Expression(copy_from->position(), kVariableProxy),
194
      next_unresolved_(nullptr) {
195
  bit_field_ = copy_from->bit_field_;
196 197
  DCHECK(!copy_from->is_resolved());
  raw_name_ = copy_from->raw_name_;
198 199
}

200
void VariableProxy::BindTo(Variable* var) {
201 202 203
  DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name());
  set_var(var);
  set_is_resolved();
204
  var->set_is_used();
205
  if (is_assigned()) var->set_maybe_assigned();
206 207
}

208 209 210
Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
                       Expression* value, int pos)
    : Expression(pos, node_type), target_(target), value_(value) {
211
  bit_field_ |= TokenField::encode(op);
212
}
213

214 215 216 217 218
bool FunctionLiteral::ShouldEagerCompile() const {
  return scope()->ShouldEagerCompile();
}

void FunctionLiteral::SetShouldEagerCompile() {
219
  scope()->set_should_eager_compile();
220
}
221 222 223 224 225

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

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

230 231 232 233 234 235 236 237 238 239
int FunctionLiteral::start_position() const {
  return scope()->start_position();
}


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


240 241
LanguageMode FunctionLiteral::language_mode() const {
  return scope()->language_mode();
242 243
}

244
FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
245

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

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
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 {
    return std::unique_ptr<char[]>(new char{'\0'});
  }

  // 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;
}

280
ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
281 282
                                             Kind kind, bool is_computed_name)
    : LiteralProperty(key, value, is_computed_name),
283
      kind_(kind),
284
      emit_store_(true) {}
285 286

ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
arv's avatar
arv committed
287 288
                                             Expression* key, Expression* value,
                                             bool is_computed_name)
289
    : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
290 291
  if (!is_computed_name && key->AsLiteral()->IsString() &&
      key->AsLiteral()->AsRawString() == ast_value_factory->proto_string()) {
292
    kind_ = PROTOTYPE;
293
  } else if (value_->AsMaterializedLiteral() != nullptr) {
294
    kind_ = MATERIALIZED_LITERAL;
295
  } else if (value_->IsLiteral()) {
296
    kind_ = CONSTANT;
297
  } else {
298
    kind_ = COMPUTED;
299 300 301
  }
}

302
bool LiteralProperty::NeedsSetFunctionName() const {
303 304 305
  return is_computed_name_ && (value_->IsAnonymousFunctionDefinition() ||
                               value_->IsConciseMethodDefinition() ||
                               value_->IsAccessorFunctionDefinition());
306
}
307

308 309 310 311 312
ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
                                           Kind kind, bool is_static,
                                           bool is_computed_name)
    : LiteralProperty(key, value, is_computed_name),
      kind_(kind),
313
      is_static_(is_static),
314
      private_or_computed_name_var_(nullptr) {}
315 316

bool ObjectLiteral::Property::IsCompileTimeValue() const {
317 318 319 320 321 322
  return kind_ == CONSTANT ||
      (kind_ == MATERIALIZED_LITERAL &&
       CompileTimeValue::IsCompileTimeValue(value_));
}


323 324 325 326
void ObjectLiteral::Property::set_emit_store(bool emit_store) {
  emit_store_ = emit_store;
}

327
bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
328

329
void ObjectLiteral::CalculateEmitStore(Zone* zone) {
330 331 332
  const auto GETTER = ObjectLiteral::Property::GETTER;
  const auto SETTER = ObjectLiteral::Property::SETTER;

333 334
  ZoneAllocationPolicy allocator(zone);

335 336
  CustomMatcherZoneHashMap table(
      Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
337 338
  for (int i = properties()->length() - 1; i >= 0; i--) {
    ObjectLiteral::Property* property = properties()->at(i);
arv's avatar
arv committed
339
    if (property->is_computed_name()) continue;
340
    if (property->IsPrototype()) continue;
arv's avatar
arv committed
341
    Literal* literal = property->key()->AsLiteral();
342
    DCHECK(!literal->IsNullLiteral());
343 344 345

    // If there is an existing entry do not emit a store unless the previous
    // entry was also an accessor.
346
    uint32_t hash = literal->Hash();
347
    ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
348
    if (entry->value != nullptr) {
349 350 351 352 353 354
      auto previous_kind =
          static_cast<ObjectLiteral::Property*>(entry->value)->kind();
      if (!((property->kind() == GETTER && previous_kind == SETTER) ||
            (property->kind() == SETTER && previous_kind == GETTER))) {
        property->set_emit_store(false);
      }
355
    }
356
    entry->value = property;
357 358 359
  }
}

360 361 362 363 364 365 366 367
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;
    }
  }
368 369
}

370 371
int ObjectLiteral::InitDepthAndFlags() {
  if (is_initialized()) return depth();
372
  bool is_simple = true;
373
  bool has_seen_prototype = false;
374
  bool needs_initial_allocation_site = false;
375
  int depth_acc = 1;
376
  uint32_t nof_properties = 0;
377
  uint32_t elements = 0;
378
  uint32_t max_element_index = 0;
379 380
  for (int i = 0; i < properties()->length(); i++) {
    ObjectLiteral::Property* property = properties()->at(i);
381 382 383 384 385 386 387 388 389
    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());
390 391 392
      is_simple = false;
      continue;
    }
393
    if (nof_properties == boilerplate_properties_) {
arv's avatar
arv committed
394
      DCHECK(property->is_computed_name());
395
      is_simple = false;
396
      if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
arv's avatar
arv committed
397 398 399 400
      break;
    }
    DCHECK(!property->is_computed_name());

401 402 403 404 405
    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();
406 407
    }

408
    Literal* key = property->key()->AsLiteral();
409 410 411 412
    Expression* value = property->value();

    bool is_compile_time_value = CompileTimeValue::IsCompileTimeValue(value);
    is_simple = is_simple && is_compile_time_value;
413 414 415 416 417 418

    // 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;
419
    if (key->AsArrayIndex(&element_index)) {
420
      max_element_index = Max(element_index, max_element_index);
421
      elements++;
422 423
    } else {
      DCHECK(key->IsPropertyName());
424 425
    }

426
    nof_properties++;
427 428
  }

429 430 431 432
  set_depth(depth_acc);
  set_is_simple(is_simple);
  set_needs_initial_allocation_site(needs_initial_allocation_site);
  set_has_elements(elements > 0);
433 434
  set_fast_elements((max_element_index <= 32) ||
                    ((2 * elements) >= max_element_index));
435
  return depth_acc;
436 437
}

438 439 440
void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
  if (!constant_properties_.is_null()) return;

441
  int index_keys = 0;
442
  bool has_seen_proto = false;
443 444
  for (int i = 0; i < properties()->length(); i++) {
    ObjectLiteral::Property* property = properties()->at(i);
445
    if (property->IsPrototype()) {
446 447 448 449
      has_seen_proto = true;
      continue;
    }
    if (property->is_computed_name()) {
450 451 452
      continue;
    }

453
    Literal* key = property->key()->AsLiteral();
454

455
    if (!key->IsPropertyName()) {
456 457 458 459
      index_keys++;
    }
  }

460
  Handle<BoilerplateDescription> constant_properties =
461 462 463
      isolate->factory()->NewBoilerplateDescription(boilerplate_properties_,
                                                    properties()->length(),
                                                    index_keys, has_seen_proto);
464 465 466 467

  int position = 0;
  for (int i = 0; i < properties()->length(); i++) {
    ObjectLiteral::Property* property = properties()->at(i);
468
    if (property->IsPrototype()) continue;
469 470 471 472 473 474 475 476

    if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
      DCHECK(property->is_computed_name());
      break;
    }
    DCHECK(!property->is_computed_name());

    MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
477
    if (m_literal != nullptr) {
478 479 480 481 482 483
      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.
484
    Literal* key_literal = property->key()->AsLiteral();
485
    uint32_t element_index = 0;
486 487 488 489 490 491
    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);
492 493 494 495 496 497 498 499 500

    // Add name, value pair to the fixed array.
    constant_properties->set(position++, *key);
    constant_properties->set(position++, *value);
  }

  constant_properties_ = constant_properties;
}

501
bool ObjectLiteral::IsFastCloningSupported() const {
502
  // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
503
  // literals don't support copy-on-write (COW) elements for now.
504
  // TODO(mvstanton): make object literals support COW elements.
505
  return fast_elements() && is_shallow() &&
506 507
         properties_count() <=
             ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
508
}
509

510 511 512 513 514 515
bool ArrayLiteral::is_empty() const {
  DCHECK(is_initialized());
  return values()->is_empty() &&
         (constant_elements().is_null() || constant_elements()->is_empty());
}

516 517
int ArrayLiteral::InitDepthAndFlags() {
  if (is_initialized()) return depth();
518

519 520
  int constants_length =
      first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
521 522

  // Fill in the literals.
523
  bool is_simple = first_spread_index_ < 0;
524 525 526 527
  int depth_acc = 1;
  int array_index = 0;
  for (; array_index < constants_length; array_index++) {
    Expression* element = values()->at(array_index);
528
    MaterializedLiteral* literal = element->AsMaterializedLiteral();
529
    if (literal != nullptr) {
530 531
      int subliteral_depth = literal->InitDepthAndFlags() + 1;
      if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
532 533 534 535 536 537 538 539
    }

    if (!CompileTimeValue::IsCompileTimeValue(element)) {
      is_simple = false;
    }
  }

  set_depth(depth_acc);
540 541 542 543 544
  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;
545 546
}

547
void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
548 549
  if (!constant_elements_.is_null()) return;

550 551
  int constants_length =
      first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
552 553 554
  ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
  Handle<FixedArray> fixed_array =
      isolate->factory()->NewFixedArrayWithHoles(constants_length);
555 556 557

  // Fill in the literals.
  bool is_holey = false;
arv's avatar
arv committed
558
  int array_index = 0;
559
  for (; array_index < constants_length; array_index++) {
arv's avatar
arv committed
560
    Expression* element = values()->at(array_index);
561
    DCHECK(!element->IsSpread());
562
    MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
563
    if (m_literal != nullptr) {
564
      m_literal->BuildConstants(isolate);
565
    }
566

567 568 569
    // New handle scope here, needs to be after BuildContants().
    HandleScope scope(isolate);
    Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
570
    if (boilerplate_value->IsTheHole(isolate)) {
571
      is_holey = true;
572 573 574
      continue;
    }

575
    if (boilerplate_value->IsUninitialized(isolate)) {
576
      boilerplate_value = handle(Smi::kZero, isolate);
577
    }
578

579 580 581
    kind = GetMoreGeneralElementsKind(kind,
                                      boilerplate_value->OptimalElementsKind());
    fixed_array->set(array_index, *boilerplate_value);
582 583
  }

584
  if (is_holey) kind = GetHoleyElementsKind(kind);
585 586 587

  // Simple and shallow arrays can be lazily copied, we transform the
  // elements array to a copy-on-write array.
588
  if (is_simple() && depth() == 1 && array_index > 0 &&
589
      IsSmiOrObjectElementsKind(kind)) {
590 591 592 593
    fixed_array->set_map(isolate->heap()->fixed_cow_array_map());
  }

  Handle<FixedArrayBase> elements = fixed_array;
594
  if (IsDoubleElementsKind(kind)) {
595 596 597 598 599
    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;
    accessor->CopyElements(fixed_array, from_kind, elements, constants_length);
600 601
  }

602 603 604
  // Remember both the literal's constant values as well as the ElementsKind.
  Handle<ConstantElementsPair> literals =
      isolate->factory()->NewConstantElementsPair(kind, elements);
605 606 607 608

  constant_elements_ = literals;
}

609 610 611
bool ArrayLiteral::IsFastCloningSupported() const {
  return depth() <= 1 &&
         values()->length() <=
612
             ConstructorBuiltins::kMaximumClonedShallowArrayElements;
613
}
614

615 616 617 618 619 620
bool MaterializedLiteral::IsSimple() const {
  if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
  if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
  DCHECK(IsRegExpLiteral());
  return false;
}
621

622 623
Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
                                                        Isolate* isolate) {
624
  if (expression->IsLiteral()) {
625
    return expression->AsLiteral()->BuildValue(isolate);
626 627 628 629 630 631 632
  }
  if (CompileTimeValue::IsCompileTimeValue(expression)) {
    return CompileTimeValue::GetValue(isolate, expression);
  }
  return isolate->factory()->uninitialized_value();
}

633 634 635 636 637 638 639 640
int MaterializedLiteral::InitDepthAndFlags() {
  if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
  if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
  DCHECK(IsRegExpLiteral());
  return 1;
}

bool MaterializedLiteral::NeedsInitialAllocationSite() {
641
  if (IsArrayLiteral()) {
642
    return AsArrayLiteral()->needs_initial_allocation_site();
643 644
  }
  if (IsObjectLiteral()) {
645
    return AsObjectLiteral()->needs_initial_allocation_site();
646 647
  }
  DCHECK(IsRegExpLiteral());
648
  return false;
649
}
650

651
void MaterializedLiteral::BuildConstants(Isolate* isolate) {
652
  if (IsArrayLiteral()) {
653
    return AsArrayLiteral()->BuildConstantElements(isolate);
654 655
  }
  if (IsObjectLiteral()) {
656
    return AsObjectLiteral()->BuildConstantProperties(isolate);
657
  }
658
  DCHECK(IsRegExpLiteral());
659 660
}

661 662 663 664 665 666
Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
    Isolate* isolate) {
  Handle<FixedArray> raw_strings =
      isolate->factory()->NewFixedArray(this->raw_strings()->length(), TENURED);
  bool raw_and_cooked_match = true;
  for (int i = 0; i < raw_strings->length(); ++i) {
667 668 669
    if (this->cooked_strings()->at(i) == nullptr ||
        *this->raw_strings()->at(i)->string() !=
            *this->cooked_strings()->at(i)->string()) {
670 671
      raw_and_cooked_match = false;
    }
672
    raw_strings->set(i, *this->raw_strings()->at(i)->string());
673 674 675 676 677 678
  }
  Handle<FixedArray> cooked_strings = raw_strings;
  if (!raw_and_cooked_match) {
    cooked_strings = isolate->factory()->NewFixedArray(
        this->cooked_strings()->length(), TENURED);
    for (int i = 0; i < cooked_strings->length(); ++i) {
679 680 681 682 683
      if (this->cooked_strings()->at(i) != nullptr) {
        cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
      } else {
        cooked_strings->set(i, isolate->heap()->undefined_value());
      }
684 685 686 687 688 689
    }
  }
  return isolate->factory()->NewTemplateObjectDescription(
      this->hash(), raw_strings, cooked_strings);
}

690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
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,
                                     Expression** expr, Smi** literal) {
  if (right->IsSmiLiteral()) {
    *expr = left;
    *literal = right->AsLiteral()->AsSmiLiteral();
    return true;
  }
  return false;
}

bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
                                            Smi** literal) {
  return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
         (IsCommutativeOperationWithSmiLiteral(op()) &&
          MatchSmiLiteralOperation(right_, left_, subexpr, literal));
}

714 715
static bool IsTypeof(Expression* expr) {
  UnaryOperation* maybe_unary = expr->AsUnaryOperation();
716
  return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
717 718 719
}

// Check for the pattern: typeof <expression> equals <string literal>.
720 721 722
static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
                                      Expression* right, Expression** expr,
                                      Literal** literal) {
723
  if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
724
    *expr = left->AsUnaryOperation()->expression();
725
    *literal = right->AsLiteral();
726 727 728 729 730
    return true;
  }
  return false;
}

731
bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
732 733 734
                                              Literal** literal) {
  return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
         MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
735
}
736 737


738 739
static bool IsVoidOfLiteral(Expression* expr) {
  UnaryOperation* maybe_unary = expr->AsUnaryOperation();
740 741
  return maybe_unary != nullptr && maybe_unary->op() == Token::VOID &&
         maybe_unary->expression()->IsLiteral();
742 743
}

744

745 746
// Check for the pattern: void <literal> equals <expression> or
// undefined equals <expression>
747 748 749
static bool MatchLiteralCompareUndefined(Expression* left,
                                         Token::Value op,
                                         Expression* right,
750
                                         Expression** expr) {
751
  if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
752 753 754
    *expr = right;
    return true;
  }
755
  if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
756
    *expr = right;
757 758 759 760 761
    return true;
  }
  return false;
}

762
bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
763 764
  return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
         MatchLiteralCompareUndefined(right_, op(), left_, expr);
765
}
766

767 768 769 770 771 772 773
// 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;
774 775 776 777 778
    return true;
  }
  return false;
}

779
bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
780 781
  return MatchLiteralCompareNull(left_, op(), right_, expr) ||
         MatchLiteralCompareNull(right_, op(), left_, expr);
782 783
}

784
Call::CallType Call::GetCallType() const {
785
  VariableProxy* proxy = expression()->AsVariableProxy();
786
  if (proxy != nullptr) {
787
    if (proxy->var()->IsUnallocated()) {
788 789
      return GLOBAL_CALL;
    } else if (proxy->var()->IsLookupSlot()) {
790 791 792
      // Calls going through 'with' always use DYNAMIC rather than DYNAMIC_LOCAL
      // or DYNAMIC_GLOBAL.
      return proxy->var()->mode() == DYNAMIC ? WITH_CALL : OTHER_CALL;
793 794 795
    }
  }

796
  if (expression()->IsSuperCallReference()) return SUPER_CALL;
797

798
  Property* property = expression()->AsProperty();
799 800
  if (property != nullptr) {
    bool is_super = property->IsSuperAccess();
801
    if (property->key()->IsPropertyName()) {
802 803 804 805 806 807
      return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
    } else {
      return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
    }
  }

808 809 810 811
  if (expression()->IsResolvedProperty()) {
    return RESOLVED_PROPERTY_CALL;
  }

812
  return OTHER_CALL;
813 814
}

815 816
CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements)
    : label_(label), statements_(statements) {}
817

818 819 820 821 822 823
bool Literal::IsPropertyName() const {
  if (type() != kString) return false;
  uint32_t index;
  return !string_->AsArrayIndex(&index);
}

824
bool Literal::ToUint32(uint32_t* value) const {
825
  switch (type()) {
826 827
    case kString:
      return string_->AsArrayIndex(value);
828 829 830 831 832 833 834 835
    case kSmi:
      if (smi_ < 0) return false;
      *value = static_cast<uint32_t>(smi_);
      return true;
    case kHeapNumber:
      return DoubleToUint32IfEqualToSelf(AsNumber(), value);
    default:
      return false;
836 837 838
  }
}

839
bool Literal::AsArrayIndex(uint32_t* value) const {
840 841 842
  return ToUint32(value) && *value != kMaxUInt32;
}

843 844 845 846 847
Handle<Object> Literal::BuildValue(Isolate* isolate) const {
  switch (type()) {
    case kSmi:
      return handle(Smi::FromInt(smi_), isolate);
    case kHeapNumber:
848
      return isolate->factory()->NewNumber(number_, TENURED);
849 850 851 852
    case kString:
      return string_->string();
    case kSymbol:
      return isolate->factory()->home_object_symbol();
853 854
    case kBoolean:
      return isolate->factory()->ToBoolean(boolean_);
855 856 857 858 859 860 861
    case kNull:
      return isolate->factory()->null_value();
    case kUndefined:
      return isolate->factory()->undefined_value();
    case kTheHole:
      return isolate->factory()->the_hole_value();
    case kBigInt:
862 863
      // This should never fail: the parser will never create a BigInt
      // literal that cannot be allocated.
864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
      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;
880 881
    case kBoolean:
      return boolean_;
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
    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();
}

902
uint32_t Literal::Hash() {
903 904
  return IsString() ? AsRawString()->Hash()
                    : ComputeLongHash(double_to_uint64(AsNumber()));
905 906 907 908
}


// static
909 910 911 912 913
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()) ||
914
         (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
915 916
}

917 918 919 920 921 922 923 924
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);
}

925 926
const char* CallRuntime::debug_name() {
#ifdef DEBUG
927 928
  return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
                        : function_->name;
929 930 931 932 933
#else
  return is_jsruntime() ? "(context function)" : function_->name;
#endif  // DEBUG
}

934 935 936 937 938 939 940 941 942 943 944 945 946 947 948
#define RETURN_LABELS(NodeType) \
  case k##NodeType:             \
    return static_cast<const NodeType*>(this)->labels();

ZoneList<const AstRawString*>* BreakableStatement::labels() const {
  switch (node_type()) {
    BREAKABLE_NODE_LIST(RETURN_LABELS)
    ITERATION_NODE_LIST(RETURN_LABELS)
    default:
      UNREACHABLE();
  }
}

#undef RETURN_LABELS

949 950
}  // namespace internal
}  // namespace v8