Line data Source code
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 :
9 : #include "src/ast/compile-time-value.h"
10 : #include "src/ast/prettyprinter.h"
11 : #include "src/ast/scopes.h"
12 : #include "src/base/hashmap.h"
13 : #include "src/builtins/builtins-constructor.h"
14 : #include "src/builtins/builtins.h"
15 : #include "src/code-stubs.h"
16 : #include "src/contexts.h"
17 : #include "src/conversions.h"
18 : #include "src/double.h"
19 : #include "src/elements.h"
20 : #include "src/objects-inl.h"
21 : #include "src/objects/literal-objects.h"
22 : #include "src/objects/map.h"
23 : #include "src/property-details.h"
24 : #include "src/property.h"
25 : #include "src/string-stream.h"
26 :
27 : namespace v8 {
28 : namespace internal {
29 :
30 : // ----------------------------------------------------------------------------
31 : // Implementation of other node functionality.
32 :
33 : #ifdef DEBUG
34 :
35 : static const char* NameForNativeContextIntrinsicIndex(uint32_t idx) {
36 : switch (idx) {
37 : #define NATIVE_CONTEXT_FIELDS_IDX(NAME, Type, name) \
38 : case Context::NAME: \
39 : return #name;
40 :
41 : NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELDS_IDX)
42 : #undef NATIVE_CONTEXT_FIELDS_IDX
43 :
44 : default:
45 : break;
46 : }
47 :
48 : return "UnknownIntrinsicIndex";
49 : }
50 :
51 : void AstNode::Print() { Print(Isolate::Current()); }
52 :
53 : void AstNode::Print(Isolate* isolate) {
54 : AllowHandleDereference allow_deref;
55 : AstPrinter::PrintOut(isolate, this);
56 : }
57 :
58 :
59 : #endif // DEBUG
60 :
61 : #define RETURN_NODE(Node) \
62 : case k##Node: \
63 : return static_cast<Node*>(this);
64 :
65 129654 : IterationStatement* AstNode::AsIterationStatement() {
66 129654 : switch (node_type()) {
67 304 : ITERATION_NODE_LIST(RETURN_NODE);
68 : default:
69 : return nullptr;
70 : }
71 : }
72 :
73 0 : BreakableStatement* AstNode::AsBreakableStatement() {
74 0 : switch (node_type()) {
75 0 : BREAKABLE_NODE_LIST(RETURN_NODE);
76 0 : ITERATION_NODE_LIST(RETURN_NODE);
77 : default:
78 : return nullptr;
79 : }
80 : }
81 :
82 26334653 : MaterializedLiteral* AstNode::AsMaterializedLiteral() {
83 26334653 : switch (node_type()) {
84 26808 : LITERAL_NODE_LIST(RETURN_NODE);
85 : default:
86 : return nullptr;
87 : }
88 : }
89 :
90 : #undef RETURN_NODE
91 :
92 944797 : bool Expression::IsSmiLiteral() const {
93 2308869 : return IsLiteral() && AsLiteral()->raw_value()->IsSmi();
94 : }
95 :
96 75 : bool Expression::IsNumberLiteral() const {
97 300 : return IsLiteral() && AsLiteral()->raw_value()->IsNumber();
98 : }
99 :
100 913513 : bool Expression::IsStringLiteral() const {
101 2694990 : return IsLiteral() && AsLiteral()->raw_value()->IsString();
102 : }
103 :
104 11821275 : bool Expression::IsPropertyName() const {
105 41586892 : return IsLiteral() && AsLiteral()->IsPropertyName();
106 : }
107 :
108 1930910 : bool Expression::IsNullLiteral() const {
109 3861820 : if (!IsLiteral()) return false;
110 1344180 : return AsLiteral()->raw_value()->IsNull();
111 : }
112 :
113 1997598 : bool Expression::IsUndefinedLiteral() const {
114 2639796 : if (IsLiteral() && AsLiteral()->raw_value()->IsUndefined()) return true;
115 :
116 2847022 : const VariableProxy* var_proxy = AsVariableProxy();
117 1979140 : if (var_proxy == nullptr) return false;
118 : Variable* var = var_proxy->var();
119 : // The global identifier "undefined" is immutable. Everything
120 : // else could be reassigned.
121 1857479 : return var != nullptr && var->IsUnallocated() &&
122 989597 : var_proxy->raw_name()->IsOneByteEqualTo("undefined");
123 : }
124 :
125 1483185 : bool Expression::ToBooleanIsTrue() const {
126 2991588 : return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
127 : }
128 :
129 1488327 : bool Expression::ToBooleanIsFalse() const {
130 3011364 : return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
131 : }
132 :
133 6535873 : bool Expression::IsValidReferenceExpression() const {
134 : // We don't want expressions wrapped inside RewritableExpression to be
135 : // considered as valid reference expressions, as they will be rewritten
136 : // to something (most probably involving a do expression).
137 6535873 : if (IsRewritableExpression()) return false;
138 9148339 : return IsProperty() ||
139 5214118 : (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
140 : }
141 :
142 12919092 : bool Expression::IsAnonymousFunctionDefinition() const {
143 1550765 : return (IsFunctionLiteral() &&
144 25391003 : AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
145 3588 : (IsClassLiteral() &&
146 12922680 : AsClassLiteral()->IsAnonymousFunctionDefinition());
147 : }
148 :
149 12469454 : bool Expression::IsConciseMethodDefinition() const {
150 26042491 : return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
151 : }
152 :
153 12027329 : bool Expression::IsAccessorFunctionDefinition() const {
154 24716118 : return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
155 : }
156 :
157 64693443 : bool Statement::IsJump() const {
158 82013704 : switch (node_type()) {
159 : #define JUMP_NODE_LIST(V) \
160 : V(Block) \
161 : V(ExpressionStatement) \
162 : V(ContinueStatement) \
163 : V(BreakStatement) \
164 : V(ReturnStatement) \
165 : V(IfStatement)
166 : #define GENERATE_CASE(Node) \
167 : case k##Node: \
168 : return static_cast<const Node*>(this)->IsJump();
169 32944267 : JUMP_NODE_LIST(GENERATE_CASE)
170 : #undef GENERATE_CASE
171 : #undef JUMP_NODE_LIST
172 : default:
173 1161693 : return false;
174 : }
175 : }
176 :
177 18036628 : VariableProxy::VariableProxy(Variable* var, int start_position)
178 : : Expression(start_position, kVariableProxy),
179 : raw_name_(var->raw_name()),
180 9018314 : next_unresolved_(nullptr) {
181 : bit_field_ |= IsThisField::encode(var->is_this()) |
182 : IsAssignedField::encode(false) |
183 : IsResolvedField::encode(false) |
184 9018314 : HoleCheckModeField::encode(HoleCheckMode::kElided);
185 : BindTo(var);
186 9018314 : }
187 :
188 5058783 : VariableProxy::VariableProxy(const VariableProxy* copy_from)
189 : : Expression(copy_from->position(), kVariableProxy),
190 10117566 : next_unresolved_(nullptr) {
191 5058783 : bit_field_ = copy_from->bit_field_;
192 : DCHECK(!copy_from->is_resolved());
193 5058783 : raw_name_ = copy_from->raw_name_;
194 5058783 : }
195 :
196 106153890 : void VariableProxy::BindTo(Variable* var) {
197 : DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name());
198 : set_var(var);
199 : set_is_resolved();
200 : var->set_is_used();
201 57586102 : if (is_assigned()) var->set_maybe_assigned();
202 48567788 : }
203 :
204 17152758 : Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
205 : Expression* value, int pos)
206 17152758 : : Expression(pos, node_type), target_(target), value_(value) {
207 17152758 : bit_field_ |= TokenField::encode(op);
208 17152758 : }
209 :
210 4231477 : bool FunctionLiteral::ShouldEagerCompile() const {
211 4231477 : return scope()->ShouldEagerCompile();
212 : }
213 :
214 741926 : void FunctionLiteral::SetShouldEagerCompile() {
215 741926 : scope()->set_should_eager_compile();
216 741927 : }
217 :
218 5166990 : bool FunctionLiteral::AllowsLazyCompilation() {
219 5166990 : return scope()->AllowsLazyCompilation();
220 : }
221 :
222 3534 : Handle<String> FunctionLiteral::name(Isolate* isolate) const {
223 7068 : return raw_name_ ? raw_name_->string() : isolate->factory()->empty_string();
224 : }
225 :
226 10717660 : int FunctionLiteral::start_position() const {
227 10717660 : return scope()->start_position();
228 : }
229 :
230 :
231 8240291 : int FunctionLiteral::end_position() const {
232 8240291 : return scope()->end_position();
233 : }
234 :
235 :
236 6529366 : LanguageMode FunctionLiteral::language_mode() const {
237 6529366 : return scope()->language_mode();
238 : }
239 :
240 14318803 : FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
241 :
242 793535 : bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
243 1587071 : if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
244 : DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
245 1306956 : return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
246 : }
247 :
248 106057 : ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
249 : Kind kind, bool is_computed_name)
250 : : LiteralProperty(key, value, is_computed_name),
251 : kind_(kind),
252 106057 : emit_store_(true) {}
253 :
254 7289530 : ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
255 : Expression* key, Expression* value,
256 : bool is_computed_name)
257 3651362 : : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
258 7289531 : if (!is_computed_name &&
259 : key->AsLiteral()->raw_value()->EqualsString(
260 7276337 : ast_value_factory->proto_string())) {
261 33634 : kind_ = PROTOTYPE;
262 7235458 : } else if (value_->AsMaterializedLiteral() != nullptr) {
263 69617 : kind_ = MATERIALIZED_LITERAL;
264 3548112 : } else if (value_->IsLiteral()) {
265 2287970 : kind_ = CONSTANT;
266 : } else {
267 1260142 : kind_ = COMPUTED;
268 : }
269 3651363 : }
270 :
271 4579633 : bool LiteralProperty::NeedsSetFunctionName() const {
272 4605382 : return is_computed_name_ && (value_->IsAnonymousFunctionDefinition() ||
273 43246 : value_->IsConciseMethodDefinition() ||
274 4597130 : value_->IsAccessorFunctionDefinition());
275 : }
276 :
277 472919 : ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
278 : Kind kind, bool is_static,
279 : bool is_computed_name)
280 : : LiteralProperty(key, value, is_computed_name),
281 : kind_(kind),
282 472919 : is_static_(is_static) {}
283 :
284 2520935 : bool ObjectLiteral::Property::IsCompileTimeValue() const {
285 2520935 : return kind_ == CONSTANT ||
286 47054 : (kind_ == MATERIALIZED_LITERAL &&
287 2567989 : CompileTimeValue::IsCompileTimeValue(value_));
288 : }
289 :
290 :
291 0 : void ObjectLiteral::Property::set_emit_store(bool emit_store) {
292 569 : emit_store_ = emit_store;
293 0 : }
294 :
295 333431 : bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
296 :
297 3258717 : void ObjectLiteral::CalculateEmitStore(Zone* zone) {
298 : const auto GETTER = ObjectLiteral::Property::GETTER;
299 : const auto SETTER = ObjectLiteral::Property::SETTER;
300 :
301 : ZoneAllocationPolicy allocator(zone);
302 :
303 : CustomMatcherZoneHashMap table(
304 : Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
305 2921008 : for (int i = properties()->length() - 1; i >= 0; i--) {
306 2584466 : ObjectLiteral::Property* property = properties()->at(i);
307 5135737 : if (property->is_computed_name()) continue;
308 2581047 : if (property->IsPrototype()) continue;
309 2552438 : Literal* literal = property->key()->AsLiteral();
310 : DCHECK(!literal->IsNullLiteral());
311 :
312 : // If there is an existing entry do not emit a store unless the previous
313 : // entry was also an accessor.
314 2552438 : uint32_t hash = literal->Hash();
315 5104876 : ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
316 2552438 : if (entry->value != nullptr) {
317 : auto previous_kind =
318 : static_cast<ObjectLiteral::Property*>(entry->value)->kind();
319 1803 : if (!((property->kind() == GETTER && previous_kind == SETTER) ||
320 1776 : (property->kind() == SETTER && previous_kind == GETTER))) {
321 : property->set_emit_store(false);
322 : }
323 : }
324 2552438 : entry->value = property;
325 : }
326 337709 : }
327 :
328 7711 : void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
329 : // We still check for __proto__:null after computed property names.
330 11560 : for (; i < properties()->length(); i++) {
331 7710 : if (properties()->at(i)->IsNullPrototype()) {
332 : set_has_null_protoype(true);
333 : break;
334 : }
335 : }
336 1931 : }
337 :
338 3295670 : int ObjectLiteral::InitDepthAndFlags() {
339 438535 : if (is_initialized()) return depth();
340 : bool is_simple = true;
341 : bool has_seen_prototype = false;
342 : bool needs_initial_allocation_site = false;
343 : int depth_acc = 1;
344 : uint32_t nof_properties = 0;
345 : uint32_t elements = 0;
346 : uint32_t max_element_index = 0;
347 5484131 : for (int i = 0; i < properties()->length(); i++) {
348 2576859 : ObjectLiteral::Property* property = properties()->at(i);
349 2576859 : if (property->IsPrototype()) {
350 : has_seen_prototype = true;
351 : // __proto__:null has no side-effects and is set directly on the
352 : // boilerplate.
353 28563 : if (property->IsNullPrototype()) {
354 : set_has_null_protoype(true);
355 28563 : continue;
356 : }
357 : DCHECK(!has_null_prototype());
358 : is_simple = false;
359 : continue;
360 : }
361 2548296 : if (nof_properties == boilerplate_properties_) {
362 : DCHECK(property->is_computed_name());
363 : is_simple = false;
364 1962 : if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
365 1962 : break;
366 : }
367 : DCHECK(!property->is_computed_name());
368 :
369 7639002 : MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
370 2546334 : if (literal != nullptr) {
371 48083 : int subliteral_depth = literal->InitDepthAndFlags() + 1;
372 48083 : if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
373 48083 : needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
374 : }
375 :
376 7639002 : const AstValue* key = property->key()->AsLiteral()->raw_value();
377 : Expression* value = property->value();
378 :
379 2546334 : bool is_compile_time_value = CompileTimeValue::IsCompileTimeValue(value);
380 2546334 : is_simple = is_simple && is_compile_time_value;
381 :
382 : // Keep track of the number of elements in the object literal and
383 : // the largest element index. If the largest element index is
384 : // much larger than the number of elements, creating an object
385 : // literal with fast elements will be a waste of space.
386 2546334 : uint32_t element_index = 0;
387 4179022 : if (key->IsString() && key->AsString()->AsArrayIndex(&element_index)) {
388 325 : max_element_index = Max(element_index, max_element_index);
389 325 : elements++;
390 2546009 : } else if (key->ToUint32(&element_index) && element_index != kMaxUInt32) {
391 913646 : max_element_index = Max(element_index, max_element_index);
392 913646 : elements++;
393 : }
394 :
395 2546334 : nof_properties++;
396 : }
397 :
398 : set_depth(depth_acc);
399 : set_is_simple(is_simple);
400 : set_needs_initial_allocation_site(needs_initial_allocation_site);
401 334337 : set_has_elements(elements > 0);
402 334905 : set_fast_elements((max_element_index <= 32) ||
403 568 : ((2 * elements) >= max_element_index));
404 334337 : return depth_acc;
405 : }
406 :
407 5972096 : void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
408 565962 : if (!constant_properties_.is_null()) return;
409 :
410 : int index_keys = 0;
411 : bool has_seen_proto = false;
412 5409013 : for (int i = 0; i < properties()->length(); i++) {
413 2563391 : ObjectLiteral::Property* property = properties()->at(i);
414 2563391 : if (property->IsPrototype()) {
415 : has_seen_proto = true;
416 23855 : continue;
417 : }
418 2540225 : if (property->is_computed_name()) {
419 : continue;
420 : }
421 :
422 5079072 : Handle<Object> key = property->key()->AsLiteral()->value();
423 :
424 2539536 : uint32_t element_index = 0;
425 6704847 : if (key->ToArrayIndex(&element_index) ||
426 1625775 : (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index))) {
427 914111 : index_keys++;
428 : }
429 : }
430 :
431 : Handle<BoilerplateDescription> constant_properties =
432 : isolate->factory()->NewBoilerplateDescription(boilerplate_properties_,
433 : properties()->length(),
434 282231 : index_keys, has_seen_proto);
435 :
436 : int position = 0;
437 5686986 : for (int i = 0; i < properties()->length(); i++) {
438 2561836 : ObjectLiteral::Property* property = properties()->at(i);
439 2584997 : if (property->IsPrototype()) continue;
440 :
441 2538675 : if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
442 : DCHECK(property->is_computed_name());
443 574 : break;
444 : }
445 : DCHECK(!property->is_computed_name());
446 :
447 7614303 : MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
448 2538101 : if (m_literal != nullptr) {
449 48083 : m_literal->BuildConstants(isolate);
450 : }
451 :
452 : // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
453 : // value for COMPUTED properties, the real value is filled in at
454 : // runtime. The enumeration order is maintained.
455 5076202 : Handle<Object> key = property->key()->AsLiteral()->value();
456 2538101 : Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
457 :
458 2538101 : uint32_t element_index = 0;
459 4162556 : if (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index)) {
460 325 : key = isolate->factory()->NewNumberFromUint(element_index);
461 3451422 : } else if (key->IsNumber() && !key->ToArrayIndex(&element_index)) {
462 0 : key = isolate->factory()->NumberToString(key);
463 : }
464 :
465 : // Add name, value pair to the fixed array.
466 5076202 : constant_properties->set(position++, *key);
467 5076202 : constant_properties->set(position++, *value);
468 : }
469 :
470 282231 : constant_properties_ = constant_properties;
471 : }
472 :
473 508181 : bool ObjectLiteral::IsFastCloningSupported() const {
474 : // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
475 : // literals don't support copy-on-write (COW) elements for now.
476 : // TODO(mvstanton): make object literals support COW elements.
477 771337 : return fast_elements() && is_shallow() &&
478 : properties_count() <=
479 263561 : ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
480 : }
481 :
482 248665 : bool ArrayLiteral::is_empty() const {
483 : DCHECK(is_initialized());
484 248665 : return values()->is_empty() &&
485 0 : (constant_elements().is_null() || constant_elements()->is_empty());
486 : }
487 :
488 8532334 : int ArrayLiteral::InitDepthAndFlags() {
489 : DCHECK_LT(first_spread_index_, 0);
490 307262 : if (is_initialized()) return depth();
491 :
492 267510 : int constants_length = values()->length();
493 :
494 : // Fill in the literals.
495 : bool is_simple = true;
496 : int depth_acc = 1;
497 : int array_index = 0;
498 8244948 : for (; array_index < constants_length; array_index++) {
499 7977438 : Expression* element = values()->at(array_index);
500 : DCHECK(!element->IsSpread());
501 : MaterializedLiteral* literal = element->AsMaterializedLiteral();
502 7977438 : if (literal != nullptr) {
503 24950 : int subliteral_depth = literal->InitDepthAndFlags() + 1;
504 24950 : if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
505 : }
506 :
507 7977438 : if (!CompileTimeValue::IsCompileTimeValue(element)) {
508 : is_simple = false;
509 : }
510 : }
511 :
512 : set_depth(depth_acc);
513 : set_is_simple(is_simple);
514 : // Array literals always need an initial allocation site to properly track
515 : // elements transitions.
516 : set_needs_initial_allocation_site(true);
517 267510 : return depth_acc;
518 : }
519 :
520 8223700 : void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
521 : DCHECK_LT(first_spread_index_, 0);
522 :
523 127279 : if (!constant_elements_.is_null()) return;
524 :
525 127279 : int constants_length = values()->length();
526 : ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
527 : Handle<FixedArray> fixed_array =
528 127279 : isolate->factory()->NewFixedArrayWithHoles(constants_length);
529 :
530 : // Fill in the literals.
531 : bool is_holey = false;
532 : int array_index = 0;
533 8096421 : for (; array_index < constants_length; array_index++) {
534 7969142 : Expression* element = values()->at(array_index);
535 : DCHECK(!element->IsSpread());
536 : MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
537 7969142 : if (m_literal != nullptr) {
538 24950 : m_literal->BuildConstants(isolate);
539 : }
540 :
541 : // New handle scope here, needs to be after BuildContants().
542 : HandleScope scope(isolate);
543 7969142 : Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
544 7969142 : if (boilerplate_value->IsTheHole(isolate)) {
545 : is_holey = true;
546 : continue;
547 : }
548 :
549 6808014 : if (boilerplate_value->IsUninitialized(isolate)) {
550 : boilerplate_value = handle(Smi::kZero, isolate);
551 : }
552 :
553 : kind = GetMoreGeneralElementsKind(kind,
554 6808014 : boilerplate_value->OptimalElementsKind());
555 6808014 : fixed_array->set(array_index, *boilerplate_value);
556 : }
557 :
558 127279 : if (is_holey) kind = GetHoleyElementsKind(kind);
559 :
560 : // Simple and shallow arrays can be lazily copied, we transform the
561 : // elements array to a copy-on-write array.
562 317435 : if (is_simple() && depth() == 1 && array_index > 0 &&
563 : IsSmiOrObjectElementsKind(kind)) {
564 102350 : fixed_array->set_map(isolate->heap()->fixed_cow_array_map());
565 : }
566 :
567 : Handle<FixedArrayBase> elements = fixed_array;
568 127279 : if (IsDoubleElementsKind(kind)) {
569 : ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
570 2489 : elements = isolate->factory()->NewFixedDoubleArray(constants_length);
571 : // We are copying from non-fast-double to fast-double.
572 : ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
573 4978 : accessor->CopyElements(fixed_array, from_kind, elements, constants_length);
574 : }
575 :
576 : // Remember both the literal's constant values as well as the ElementsKind.
577 : Handle<ConstantElementsPair> literals =
578 127279 : isolate->factory()->NewConstantElementsPair(kind, elements);
579 :
580 127279 : constant_elements_ = literals;
581 : }
582 :
583 218280 : bool ArrayLiteral::IsFastCloningSupported() const {
584 218280 : return depth() <= 1 &&
585 106821 : values()->length() <=
586 111459 : ConstructorBuiltins::kMaximumClonedShallowArrayElements;
587 : }
588 :
589 2112 : void ArrayLiteral::RewindSpreads() {
590 2112 : values_->Rewind(first_spread_index_);
591 2112 : first_spread_index_ = -1;
592 2112 : }
593 :
594 216549 : bool MaterializedLiteral::IsSimple() const {
595 331499 : if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
596 450468 : if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
597 : DCHECK(IsRegExpLiteral());
598 : return false;
599 : }
600 :
601 10507243 : Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
602 : Isolate* isolate) {
603 10507243 : if (expression->IsLiteral()) {
604 19694352 : return expression->AsLiteral()->value();
605 : }
606 660067 : if (CompileTimeValue::IsCompileTimeValue(expression)) {
607 41259 : return CompileTimeValue::GetValue(isolate, expression);
608 : }
609 618808 : return isolate->factory()->uninitialized_value();
610 : }
611 :
612 73033 : int MaterializedLiteral::InitDepthAndFlags() {
613 92880 : if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
614 101913 : if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
615 : DCHECK(IsRegExpLiteral());
616 : return 1;
617 : }
618 :
619 48083 : bool MaterializedLiteral::NeedsInitialAllocationSite() {
620 48083 : if (IsArrayLiteral()) {
621 29271 : return AsArrayLiteral()->needs_initial_allocation_site();
622 : }
623 38326 : if (IsObjectLiteral()) {
624 102399 : return AsObjectLiteral()->needs_initial_allocation_site();
625 : }
626 : DCHECK(IsRegExpLiteral());
627 : return false;
628 : }
629 :
630 73033 : void MaterializedLiteral::BuildConstants(Isolate* isolate) {
631 73033 : if (IsArrayLiteral()) {
632 39694 : return AsArrayLiteral()->BuildConstantElements(isolate);
633 : }
634 53186 : if (IsObjectLiteral()) {
635 97454 : return AsObjectLiteral()->BuildConstantProperties(isolate);
636 : }
637 : DCHECK(IsRegExpLiteral());
638 : }
639 :
640 1439 : Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
641 10843 : Isolate* isolate) {
642 : Handle<FixedArray> raw_strings =
643 1439 : isolate->factory()->NewFixedArray(this->raw_strings()->length(), TENURED);
644 : bool raw_and_cooked_match = true;
645 7868 : for (int i = 0; i < raw_strings->length(); ++i) {
646 4990 : if (*this->raw_strings()->at(i)->value() !=
647 2495 : *this->cooked_strings()->at(i)->value()) {
648 : raw_and_cooked_match = false;
649 : }
650 2495 : raw_strings->set(i, *this->raw_strings()->at(i)->value());
651 : }
652 : Handle<FixedArray> cooked_strings = raw_strings;
653 1439 : if (!raw_and_cooked_match) {
654 : cooked_strings = isolate->factory()->NewFixedArray(
655 1062 : this->cooked_strings()->length(), TENURED);
656 5950 : for (int i = 0; i < cooked_strings->length(); ++i) {
657 3826 : cooked_strings->set(i, *this->cooked_strings()->at(i)->value());
658 : }
659 : }
660 : return isolate->factory()->NewTemplateObjectDescription(
661 1439 : this->hash(), raw_strings, cooked_strings);
662 : }
663 :
664 : static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
665 : // Add is not commutative due to potential for string addition.
666 603336 : return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
667 : op == Token::BIT_XOR;
668 : }
669 :
670 : // Check for the pattern: x + 1.
671 844100 : static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
672 : Expression** expr, Smi** literal) {
673 844100 : if (right->IsSmiLiteral()) {
674 181417 : *expr = left;
675 362834 : *literal = right->AsLiteral()->AsSmiLiteral();
676 181417 : return true;
677 : }
678 : return false;
679 : }
680 :
681 766484 : bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
682 603336 : Smi** literal) {
683 1369820 : return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
684 77616 : (IsCommutativeOperationWithSmiLiteral(op()) &&
685 844100 : MatchSmiLiteralOperation(right_, left_, subexpr, literal));
686 : }
687 :
688 2179202 : static bool IsTypeof(Expression* expr) {
689 2407972 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
690 2407972 : return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
691 : }
692 :
693 : // Check for the pattern: typeof <expression> equals <string literal>.
694 2179202 : static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
695 : Expression* right, Expression** expr,
696 : Literal** literal) {
697 2324804 : if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
698 291204 : *expr = left->AsUnaryOperation()->expression();
699 291204 : *literal = right->AsLiteral();
700 145602 : return true;
701 : }
702 : return false;
703 : }
704 :
705 1162365 : bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
706 2179202 : Literal** literal) {
707 3341567 : return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
708 3196039 : MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
709 : }
710 :
711 :
712 2032436 : static bool IsVoidOfLiteral(Expression* expr) {
713 2157086 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
714 2157086 : return maybe_unary != nullptr && maybe_unary->op() == Token::VOID &&
715 2032436 : maybe_unary->expression()->IsLiteral();
716 : }
717 :
718 :
719 : // Check for the pattern: void <literal> equals <expression> or
720 : // undefined equals <expression>
721 2032436 : static bool MatchLiteralCompareUndefined(Expression* left,
722 : Token::Value op,
723 : Expression* right,
724 : Expression** expr) {
725 2074310 : if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
726 40938 : *expr = right;
727 40938 : return true;
728 : }
729 2030303 : if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
730 38757 : *expr = right;
731 38757 : return true;
732 : }
733 : return false;
734 : }
735 :
736 3049199 : bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
737 3049199 : return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
738 3048109 : MatchLiteralCompareUndefined(right_, op(), left_, expr);
739 : }
740 :
741 : // Check for the pattern: null equals <expression>
742 1873374 : static bool MatchLiteralCompareNull(Expression* left,
743 : Token::Value op,
744 : Expression* right,
745 : Expression** expr) {
746 1929072 : if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
747 54734 : *expr = right;
748 54734 : return true;
749 : }
750 : return false;
751 : }
752 :
753 2810442 : bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
754 2810442 : return MatchLiteralCompareNull(left_, op(), right_, expr) ||
755 2809680 : MatchLiteralCompareNull(right_, op(), left_, expr);
756 : }
757 :
758 5446772 : Call::CallType Call::GetCallType() const {
759 4400737 : VariableProxy* proxy = expression()->AsVariableProxy();
760 2665848 : if (proxy != nullptr) {
761 1734890 : if (proxy->var()->IsUnallocated()) {
762 : return GLOBAL_CALL;
763 647800 : } else if (proxy->var()->IsLookupSlot()) {
764 : // Calls going through 'with' always use DYNAMIC rather than DYNAMIC_LOCAL
765 : // or DYNAMIC_GLOBAL.
766 186414 : return proxy->var()->mode() == DYNAMIC ? WITH_CALL : OTHER_CALL;
767 : }
768 : }
769 :
770 2784687 : if (expression()->IsSuperCallReference()) return SUPER_CALL;
771 :
772 2224454 : Property* property = expression()->AsProperty();
773 1388581 : if (property != nullptr) {
774 835873 : bool is_super = property->IsSuperAccess();
775 835873 : if (property->key()->IsPropertyName()) {
776 831566 : return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
777 : } else {
778 4307 : return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
779 : }
780 : }
781 :
782 : return OTHER_CALL;
783 : }
784 :
785 109361 : CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements)
786 109361 : : label_(label), statements_(statements) {}
787 :
788 2557030 : uint32_t Literal::Hash() {
789 2557030 : return raw_value()->IsString()
790 1643254 : ? raw_value()->AsString()->Hash()
791 6027836 : : ComputeLongHash(double_to_uint64(raw_value()->AsNumber()));
792 : }
793 :
794 :
795 : // static
796 64323 : bool Literal::Match(void* literal1, void* literal2) {
797 64323 : const AstValue* x = static_cast<Literal*>(literal1)->raw_value();
798 63451 : const AstValue* y = static_cast<Literal*>(literal2)->raw_value();
799 192673 : return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) ||
800 872 : (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
801 : }
802 :
803 0 : const char* CallRuntime::debug_name() {
804 : #ifdef DEBUG
805 : return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
806 : : function_->name;
807 : #else
808 0 : return is_jsruntime() ? "(context function)" : function_->name;
809 : #endif // DEBUG
810 : }
811 :
812 : #define RETURN_LABELS(NodeType) \
813 : case k##NodeType: \
814 : return static_cast<const NodeType*>(this)->labels();
815 :
816 45167 : ZoneList<const AstRawString*>* BreakableStatement::labels() const {
817 89796 : switch (node_type()) {
818 32748 : BREAKABLE_NODE_LIST(RETURN_LABELS)
819 3151 : ITERATION_NODE_LIST(RETURN_LABELS)
820 : default:
821 0 : UNREACHABLE();
822 : }
823 : }
824 :
825 : #undef RETURN_LABELS
826 :
827 : } // namespace internal
828 : } // namespace v8
|