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 : #include <vector>
9 :
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/contexts.h"
16 : #include "src/conversions-inl.h"
17 : #include "src/double.h"
18 : #include "src/elements.h"
19 : #include "src/objects-inl.h"
20 : #include "src/objects/literal-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 : #include "src/zone/zone-list-inl.h"
27 :
28 : namespace v8 {
29 : namespace internal {
30 :
31 : // ----------------------------------------------------------------------------
32 : // Implementation of other node functionality.
33 :
34 : #ifdef DEBUG
35 :
36 : static const char* NameForNativeContextIntrinsicIndex(uint32_t idx) {
37 : switch (idx) {
38 : #define NATIVE_CONTEXT_FIELDS_IDX(NAME, Type, name) \
39 : case Context::NAME: \
40 : return #name;
41 :
42 : NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELDS_IDX)
43 : #undef NATIVE_CONTEXT_FIELDS_IDX
44 :
45 : default:
46 : break;
47 : }
48 :
49 : return "UnknownIntrinsicIndex";
50 : }
51 :
52 : void AstNode::Print() { Print(Isolate::Current()); }
53 :
54 : void AstNode::Print(Isolate* isolate) {
55 : AllowHandleDereference allow_deref;
56 : AstPrinter::PrintOut(isolate, this);
57 : }
58 :
59 :
60 : #endif // DEBUG
61 :
62 : #define RETURN_NODE(Node) \
63 : case k##Node: \
64 : return static_cast<Node*>(this);
65 :
66 33520 : IterationStatement* AstNode::AsIterationStatement() {
67 33520 : switch (node_type()) {
68 345 : ITERATION_NODE_LIST(RETURN_NODE);
69 : default:
70 : return nullptr;
71 : }
72 : }
73 :
74 21199180 : MaterializedLiteral* AstNode::AsMaterializedLiteral() {
75 22460804 : switch (node_type()) {
76 63973 : LITERAL_NODE_LIST(RETURN_NODE);
77 : default:
78 : return nullptr;
79 : }
80 : }
81 :
82 : #undef RETURN_NODE
83 :
84 838183 : bool Expression::IsSmiLiteral() const {
85 1586002 : return IsLiteral() && AsLiteral()->type() == Literal::kSmi;
86 : }
87 :
88 2780866 : bool Expression::IsNumberLiteral() const {
89 4589231 : return IsLiteral() && AsLiteral()->IsNumber();
90 : }
91 :
92 394213 : bool Expression::IsStringLiteral() const {
93 1080922 : return IsLiteral() && AsLiteral()->type() == Literal::kString;
94 : }
95 :
96 9177869 : bool Expression::IsPropertyName() const {
97 16486206 : return IsLiteral() && AsLiteral()->IsPropertyName();
98 : }
99 :
100 1446632 : bool Expression::IsNullLiteral() const {
101 2233785 : return IsLiteral() && AsLiteral()->type() == Literal::kNull;
102 : }
103 :
104 5109 : bool Expression::IsTheHoleLiteral() const {
105 6675 : return IsLiteral() && AsLiteral()->type() == Literal::kTheHole;
106 : }
107 :
108 16923760 : bool Expression::IsCompileTimeValue() {
109 16923827 : if (IsLiteral()) return true;
110 : MaterializedLiteral* literal = AsMaterializedLiteral();
111 1261624 : if (literal == nullptr) return false;
112 222744 : return literal->IsSimple();
113 : }
114 :
115 1557792 : bool Expression::IsUndefinedLiteral() const {
116 2354124 : if (IsLiteral() && AsLiteral()->type() == Literal::kUndefined) return true;
117 :
118 2229412 : const VariableProxy* var_proxy = AsVariableProxy();
119 1548256 : if (var_proxy == nullptr) return false;
120 : Variable* var = var_proxy->var();
121 : // The global identifier "undefined" is immutable. Everything
122 : // else could be reassigned.
123 1568203 : return var != nullptr && var->IsUnallocated() &&
124 887060 : var_proxy->raw_name()->IsOneByteEqualTo("undefined");
125 : }
126 :
127 948335 : bool Expression::ToBooleanIsTrue() const {
128 972326 : return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
129 : }
130 :
131 933561 : bool Expression::ToBooleanIsFalse() const {
132 966936 : return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
133 : }
134 :
135 0 : bool Expression::IsValidReferenceExpression() const {
136 0 : return IsProperty() ||
137 0 : (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
138 : }
139 :
140 11811279 : bool Expression::IsAnonymousFunctionDefinition() const {
141 1607670 : return (IsFunctionLiteral() &&
142 23276356 : AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
143 3687 : (IsClassLiteral() &&
144 11815013 : AsClassLiteral()->IsAnonymousFunctionDefinition());
145 : }
146 :
147 11462682 : bool Expression::IsConciseMethodDefinition() const {
148 12723993 : return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
149 : }
150 :
151 11105432 : bool Expression::IsAccessorFunctionDefinition() const {
152 12009387 : return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
153 : }
154 :
155 5795596 : VariableProxy::VariableProxy(Variable* var, int start_position)
156 : : Expression(start_position, kVariableProxy),
157 : raw_name_(var->raw_name()),
158 2897798 : next_unresolved_(nullptr) {
159 : DCHECK(!var->is_this());
160 : bit_field_ |= IsAssignedField::encode(false) |
161 : IsResolvedField::encode(false) |
162 2897798 : HoleCheckModeField::encode(HoleCheckMode::kElided);
163 : BindTo(var);
164 2897798 : }
165 :
166 6503508 : VariableProxy::VariableProxy(const VariableProxy* copy_from)
167 : : Expression(copy_from->position(), kVariableProxy),
168 13007016 : next_unresolved_(nullptr) {
169 6503508 : bit_field_ = copy_from->bit_field_;
170 : DCHECK(!copy_from->is_resolved());
171 6503508 : raw_name_ = copy_from->raw_name_;
172 6503508 : }
173 :
174 81416788 : void VariableProxy::BindTo(Variable* var) {
175 : DCHECK_EQ(raw_name(), var->raw_name());
176 : set_var(var);
177 : set_is_resolved();
178 : var->set_is_used();
179 42157293 : if (is_assigned()) var->set_maybe_assigned();
180 39259495 : }
181 :
182 14168333 : Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
183 : Expression* value, int pos)
184 14168333 : : Expression(pos, node_type), target_(target), value_(value) {
185 14168333 : bit_field_ |= TokenField::encode(op);
186 14168333 : }
187 :
188 1402480 : void FunctionLiteral::set_inferred_name(Handle<String> inferred_name) {
189 : DCHECK(!inferred_name.is_null());
190 701240 : inferred_name_ = inferred_name;
191 : DCHECK(raw_inferred_name_ == nullptr || raw_inferred_name_->IsEmpty());
192 701240 : raw_inferred_name_ = nullptr;
193 : scope()->set_has_inferred_function_name(true);
194 701240 : }
195 :
196 461906 : void FunctionLiteral::set_raw_inferred_name(
197 461906 : const AstConsString* raw_inferred_name) {
198 : DCHECK_NOT_NULL(raw_inferred_name);
199 461906 : raw_inferred_name_ = raw_inferred_name;
200 : DCHECK(inferred_name_.is_null());
201 461906 : inferred_name_ = Handle<String>();
202 : scope()->set_has_inferred_function_name(true);
203 461906 : }
204 :
205 6471715 : bool FunctionLiteral::ShouldEagerCompile() const {
206 6471715 : return scope()->ShouldEagerCompile();
207 : }
208 :
209 716694 : void FunctionLiteral::SetShouldEagerCompile() {
210 716694 : scope()->set_should_eager_compile();
211 716717 : }
212 :
213 3576899 : bool FunctionLiteral::AllowsLazyCompilation() {
214 3576899 : return scope()->AllowsLazyCompilation();
215 : }
216 :
217 0 : Handle<String> FunctionLiteral::name(Isolate* isolate) const {
218 0 : return raw_name_ ? raw_name_->string() : isolate->factory()->empty_string();
219 : }
220 :
221 10794317 : int FunctionLiteral::start_position() const {
222 10794317 : return scope()->start_position();
223 : }
224 :
225 :
226 5117354 : int FunctionLiteral::end_position() const {
227 5117354 : return scope()->end_position();
228 : }
229 :
230 :
231 4912447 : LanguageMode FunctionLiteral::language_mode() const {
232 4912447 : return scope()->language_mode();
233 : }
234 :
235 12172869 : FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
236 :
237 293320 : bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
238 586643 : if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
239 : DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
240 306843 : return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
241 : }
242 :
243 23 : std::unique_ptr<char[]> FunctionLiteral::GetDebugName() const {
244 : const AstConsString* cons_string;
245 23 : if (raw_name_ != nullptr && !raw_name_->IsEmpty()) {
246 : cons_string = raw_name_;
247 6 : } else if (raw_inferred_name_ != nullptr && !raw_inferred_name_->IsEmpty()) {
248 : cons_string = raw_inferred_name_;
249 6 : } else if (!inferred_name_.is_null()) {
250 : AllowHandleDereference allow_deref;
251 6 : return inferred_name_->ToCString();
252 : } else {
253 0 : char* empty_str = new char[1];
254 0 : empty_str[0] = 0;
255 : return std::unique_ptr<char[]>(empty_str);
256 : }
257 :
258 : // TODO(rmcilroy): Deal with two-character strings.
259 : std::vector<char> result_vec;
260 17 : std::forward_list<const AstRawString*> strings = cons_string->ToRawStrings();
261 51 : for (const AstRawString* string : strings) {
262 17 : if (!string->is_one_byte()) break;
263 335 : for (int i = 0; i < string->length(); i++) {
264 318 : result_vec.push_back(string->raw_data()[i]);
265 : }
266 : }
267 34 : std::unique_ptr<char[]> result(new char[result_vec.size() + 1]);
268 17 : memcpy(result.get(), result_vec.data(), result_vec.size());
269 34 : result[result_vec.size()] = '\0';
270 : return result;
271 : }
272 :
273 136954 : ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
274 : Kind kind, bool is_computed_name)
275 : : LiteralProperty(key, value, is_computed_name),
276 : kind_(kind),
277 136954 : emit_store_(true) {}
278 :
279 4337756 : ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
280 : Expression* key, Expression* value,
281 : bool is_computed_name)
282 2899167 : : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
283 7223160 : if (!is_computed_name && key->AsLiteral()->IsString() &&
284 1438589 : key->AsLiteral()->AsRawString() == ast_value_factory->proto_string()) {
285 6587 : kind_ = PROTOTYPE;
286 2892638 : } else if (value_->AsMaterializedLiteral() != nullptr) {
287 59556 : kind_ = MATERIALIZED_LITERAL;
288 2833056 : } else if (value_->IsLiteral()) {
289 1851541 : kind_ = CONSTANT;
290 : } else {
291 981515 : kind_ = COMPUTED;
292 : }
293 2899199 : }
294 :
295 3390410 : bool LiteralProperty::NeedsSetFunctionName() const {
296 3419745 : return is_computed_name() && (value_->IsAnonymousFunctionDefinition() ||
297 51771 : value_->IsConciseMethodDefinition() ||
298 3412849 : value_->IsAccessorFunctionDefinition());
299 : }
300 :
301 436427 : ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
302 : Kind kind, bool is_static,
303 : bool is_computed_name,
304 : bool is_private)
305 : : LiteralProperty(key, value, is_computed_name),
306 : kind_(kind),
307 : is_static_(is_static),
308 : is_private_(is_private),
309 436427 : private_or_computed_name_var_(nullptr) {}
310 :
311 2007299 : bool ObjectLiteral::Property::IsCompileTimeValue() const {
312 2007299 : return kind_ == CONSTANT ||
313 43992 : (kind_ == MATERIALIZED_LITERAL && value_->IsCompileTimeValue());
314 : }
315 :
316 :
317 0 : void ObjectLiteral::Property::set_emit_store(bool emit_store) {
318 3363 : emit_store_ = emit_store;
319 0 : }
320 :
321 247388 : bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
322 :
323 586981 : void ObjectLiteral::CalculateEmitStore(Zone* zone) {
324 : const auto GETTER = ObjectLiteral::Property::GETTER;
325 : const auto SETTER = ObjectLiteral::Property::SETTER;
326 :
327 : ZoneAllocationPolicy allocator(zone);
328 :
329 : CustomMatcherZoneHashMap table(
330 : Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
331 3594868 : for (int i = properties()->length() - 1; i >= 0; i--) {
332 3011884 : ObjectLiteral::Property* property = properties()->at(i);
333 3007804 : if (property->is_computed_name()) continue;
334 2986913 : if (property->IsPrototype()) continue;
335 2980279 : Literal* literal = property->key()->AsLiteral();
336 : DCHECK(!literal->IsNullLiteral());
337 :
338 2980282 : uint32_t hash = literal->Hash();
339 5960519 : ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
340 2984376 : if (entry->value == nullptr) {
341 2976216 : entry->value = property;
342 : } else {
343 : // We already have a later definition of this property, so we don't need
344 : // to emit a store for the current one.
345 : //
346 : // There are two subtleties here.
347 : //
348 : // (1) Emitting a store might actually be incorrect. For example, in {get
349 : // foo() {}, foo: 42}, the getter store would override the data property
350 : // (which, being a non-computed compile-time valued property, is already
351 : // part of the initial literal object.
352 : //
353 : // (2) If the later definition is an accessor (say, a getter), and the
354 : // current definition is a complementary accessor (here, a setter), then
355 : // we still must emit a store for the current definition.
356 :
357 : auto later_kind =
358 : static_cast<ObjectLiteral::Property*>(entry->value)->kind();
359 : bool complementary_accessors =
360 4080 : (property->kind() == GETTER && later_kind == SETTER) ||
361 204 : (property->kind() == SETTER && later_kind == GETTER);
362 4080 : if (!complementary_accessors) {
363 : property->set_emit_store(false);
364 3363 : if (later_kind == GETTER || later_kind == SETTER) {
365 1066 : entry->value = property;
366 : }
367 : }
368 : }
369 : }
370 587064 : }
371 :
372 2091 : void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
373 : // We still check for __proto__:null after computed property names.
374 5145 : for (; i < properties()->length(); i++) {
375 6118 : if (properties()->at(i)->IsNullPrototype()) {
376 : set_has_null_protoype(true);
377 : break;
378 : }
379 : }
380 2091 : }
381 :
382 262509 : int ObjectLiteral::InitDepthAndFlags() {
383 280260 : if (is_initialized()) return depth();
384 : bool is_simple = true;
385 : bool has_seen_prototype = false;
386 : bool needs_initial_allocation_site = false;
387 : int depth_acc = 1;
388 : uint32_t nof_properties = 0;
389 : uint32_t elements = 0;
390 : uint32_t max_element_index = 0;
391 2038763 : for (int i = 0; i < properties()->length(); i++) {
392 2040861 : ObjectLiteral::Property* property = properties()->at(i);
393 2040861 : if (property->IsPrototype()) {
394 : has_seen_prototype = true;
395 : // __proto__:null has no side-effects and is set directly on the
396 : // boilerplate.
397 4091 : if (property->IsNullPrototype()) {
398 : set_has_null_protoype(true);
399 4091 : continue;
400 : }
401 : DCHECK(!has_null_prototype());
402 : is_simple = false;
403 : continue;
404 : }
405 2036787 : if (nof_properties == boilerplate_properties_) {
406 : DCHECK(property->is_computed_name());
407 : is_simple = false;
408 2124 : if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
409 2124 : break;
410 : }
411 : DCHECK(!property->is_computed_name());
412 :
413 4069306 : MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
414 2034663 : if (literal != nullptr) {
415 45458 : int subliteral_depth = literal->InitDepthAndFlags() + 1;
416 45458 : if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
417 45458 : needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
418 : }
419 :
420 2034662 : Literal* key = property->key()->AsLiteral();
421 : Expression* value = property->value();
422 :
423 2034643 : bool is_compile_time_value = value->IsCompileTimeValue();
424 2034695 : is_simple = is_simple && is_compile_time_value;
425 :
426 : // Keep track of the number of elements in the object literal and
427 : // the largest element index. If the largest element index is
428 : // much larger than the number of elements, creating an object
429 : // literal with fast elements will be a waste of space.
430 2034695 : uint32_t element_index = 0;
431 2034672 : if (key->AsArrayIndex(&element_index)) {
432 784534 : max_element_index = Max(element_index, max_element_index);
433 784534 : elements++;
434 : } else {
435 : DCHECK(key->IsPropertyName());
436 : }
437 :
438 2034672 : nof_properties++;
439 : }
440 :
441 : set_depth(depth_acc);
442 : set_is_simple(is_simple);
443 : set_needs_initial_allocation_site(needs_initial_allocation_site);
444 244784 : set_has_elements(elements > 0);
445 245321 : set_fast_elements((max_element_index <= 32) ||
446 537 : ((2 * elements) >= max_element_index));
447 244784 : return depth_acc;
448 : }
449 :
450 204176 : void ObjectLiteral::BuildBoilerplateDescription(Isolate* isolate) {
451 408357 : if (!boilerplate_description_.is_null()) return;
452 :
453 : int index_keys = 0;
454 : bool has_seen_proto = false;
455 1957366 : for (int i = 0; i < properties()->length(); i++) {
456 1957364 : ObjectLiteral::Property* property = properties()->at(i);
457 1957364 : if (property->IsPrototype()) {
458 : has_seen_proto = true;
459 : continue;
460 : }
461 1954080 : if (property->is_computed_name()) continue;
462 :
463 1953534 : Literal* key = property->key()->AsLiteral();
464 1953538 : if (!key->IsPropertyName()) index_keys++;
465 : }
466 :
467 : Handle<ObjectBoilerplateDescription> boilerplate_description =
468 : isolate->factory()->NewObjectBoilerplateDescription(
469 : boilerplate_properties_, properties()->length(), index_keys,
470 202070 : has_seen_proto);
471 :
472 : int position = 0;
473 2158596 : for (int i = 0; i < properties()->length(); i++) {
474 1956947 : ObjectLiteral::Property* property = properties()->at(i);
475 1960227 : if (property->IsPrototype()) continue;
476 :
477 1953667 : if (static_cast<uint32_t>(position) == boilerplate_properties_) {
478 : DCHECK(property->is_computed_name());
479 424 : break;
480 : }
481 : DCHECK(!property->is_computed_name());
482 :
483 3906488 : MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
484 1953243 : if (m_literal != nullptr) {
485 44163 : m_literal->BuildConstants(isolate);
486 : }
487 :
488 : // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
489 : // value for COMPUTED properties, the real value is filled in at
490 : // runtime. The enumeration order is maintained.
491 3123684 : Literal* key_literal = property->key()->AsLiteral();
492 1953244 : uint32_t element_index = 0;
493 : Handle<Object> key =
494 : key_literal->AsArrayIndex(&element_index)
495 782804 : ? isolate->factory()->NewNumberFromUint(element_index)
496 3906490 : : Handle<Object>::cast(key_literal->AsRawPropertyName()->string());
497 :
498 1953245 : Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
499 :
500 : // Add name, value pair to the fixed array.
501 3906490 : boilerplate_description->set_key_value(position++, *key, *value);
502 : }
503 :
504 : boilerplate_description->set_flags(EncodeLiteralType());
505 :
506 202073 : boilerplate_description_ = boilerplate_description;
507 : }
508 :
509 380765 : bool ObjectLiteral::IsFastCloningSupported() const {
510 : // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
511 : // literals don't support copy-on-write (COW) elements for now.
512 : // TODO(mvstanton): make object literals support COW elements.
513 579931 : return fast_elements() && is_shallow() &&
514 : properties_count() <=
515 199553 : ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
516 : }
517 :
518 387239 : int ArrayLiteral::InitDepthAndFlags() {
519 392004 : if (is_initialized()) return depth();
520 :
521 : int constants_length =
522 382474 : first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
523 :
524 : // Fill in the literals.
525 382474 : bool is_simple = first_spread_index_ < 0;
526 : int depth_acc = 1;
527 : int array_index = 0;
528 7594750 : for (; array_index < constants_length; array_index++) {
529 7212253 : Expression* element = values()->at(array_index);
530 : MaterializedLiteral* literal = element->AsMaterializedLiteral();
531 7212253 : if (literal != nullptr) {
532 31474 : int subliteral_depth = literal->InitDepthAndFlags() + 1;
533 31473 : if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
534 : }
535 :
536 7212252 : if (!element->IsCompileTimeValue()) {
537 : is_simple = false;
538 : }
539 : }
540 :
541 : set_depth(depth_acc);
542 : set_is_simple(is_simple);
543 : // Array literals always need an initial allocation site to properly track
544 : // elements transitions.
545 : set_needs_initial_allocation_site(true);
546 382497 : return depth_acc;
547 : }
548 :
549 165022 : void ArrayLiteral::BuildBoilerplateDescription(Isolate* isolate) {
550 165022 : if (!boilerplate_description_.is_null()) return;
551 :
552 : int constants_length =
553 165022 : first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
554 : ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
555 : Handle<FixedArray> fixed_array =
556 165022 : isolate->factory()->NewFixedArrayWithHoles(constants_length);
557 :
558 : // Fill in the literals.
559 : bool is_holey = false;
560 : int array_index = 0;
561 7271405 : for (; array_index < constants_length; array_index++) {
562 7106383 : Expression* element = values()->at(array_index);
563 : DCHECK(!element->IsSpread());
564 : MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
565 7106383 : if (m_literal != nullptr) {
566 28699 : m_literal->BuildConstants(isolate);
567 : }
568 :
569 : // New handle scope here, needs to be after BuildContants().
570 : HandleScope scope(isolate);
571 7106383 : Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
572 14212763 : if (boilerplate_value->IsTheHole(isolate)) {
573 : is_holey = true;
574 : continue;
575 : }
576 :
577 12073679 : if (boilerplate_value->IsUninitialized(isolate)) {
578 : boilerplate_value = handle(Smi::kZero, isolate);
579 : }
580 :
581 : kind = GetMoreGeneralElementsKind(kind,
582 12073682 : boilerplate_value->OptimalElementsKind());
583 6036842 : fixed_array->set(array_index, *boilerplate_value);
584 : }
585 :
586 165022 : if (is_holey) kind = GetHoleyElementsKind(kind);
587 :
588 : // Simple and shallow arrays can be lazily copied, we transform the
589 : // elements array to a copy-on-write array.
590 404713 : if (is_simple() && depth() == 1 && array_index > 0 &&
591 : IsSmiOrObjectElementsKind(kind)) {
592 54753 : fixed_array->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
593 : }
594 :
595 : Handle<FixedArrayBase> elements = fixed_array;
596 165021 : if (IsDoubleElementsKind(kind)) {
597 : ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
598 3306 : elements = isolate->factory()->NewFixedDoubleArray(constants_length);
599 : // We are copying from non-fast-double to fast-double.
600 : ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
601 : accessor->CopyElements(isolate, fixed_array, from_kind, elements,
602 6612 : constants_length);
603 : }
604 :
605 : boilerplate_description_ =
606 165021 : isolate->factory()->NewArrayBoilerplateDescription(kind, elements);
607 : }
608 :
609 354318 : bool ArrayLiteral::IsFastCloningSupported() const {
610 701755 : return depth() <= 1 &&
611 347437 : values_.length() <=
612 354318 : ConstructorBuiltins::kMaximumClonedShallowArrayElements;
613 : }
614 :
615 222740 : bool MaterializedLiteral::IsSimple() const {
616 397796 : if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
617 341566 : if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
618 : DCHECK(IsRegExpLiteral());
619 : return false;
620 : }
621 :
622 9059628 : Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
623 : Isolate* isolate) {
624 9059628 : if (expression->IsLiteral()) {
625 17188426 : return expression->AsLiteral()->BuildValue(isolate);
626 : }
627 465415 : if (expression->IsCompileTimeValue()) {
628 40880 : if (expression->IsObjectLiteral()) {
629 16648 : ObjectLiteral* object_literal = expression->AsObjectLiteral();
630 : DCHECK(object_literal->is_simple());
631 16648 : return object_literal->boilerplate_description();
632 : } else {
633 : DCHECK(expression->IsArrayLiteral());
634 24232 : ArrayLiteral* array_literal = expression->AsArrayLiteral();
635 : DCHECK(array_literal->is_simple());
636 24232 : return array_literal->boilerplate_description();
637 : }
638 : }
639 424535 : return isolate->factory()->uninitialized_value();
640 : }
641 :
642 76928 : int MaterializedLiteral::InitDepthAndFlags() {
643 107824 : if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
644 81387 : if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
645 : DCHECK(IsRegExpLiteral());
646 : return 1;
647 : }
648 :
649 45458 : bool MaterializedLiteral::NeedsInitialAllocationSite() {
650 45458 : if (IsArrayLiteral()) {
651 52563 : return AsArrayLiteral()->needs_initial_allocation_site();
652 : }
653 27937 : if (IsObjectLiteral()) {
654 52626 : return AsObjectLiteral()->needs_initial_allocation_site();
655 : }
656 : DCHECK(IsRegExpLiteral());
657 : return false;
658 : }
659 :
660 72861 : void MaterializedLiteral::BuildConstants(Isolate* isolate) {
661 72862 : if (IsArrayLiteral()) {
662 57052 : AsArrayLiteral()->BuildBoilerplateDescription(isolate);
663 28526 : return;
664 : }
665 44336 : if (IsObjectLiteral()) {
666 67346 : AsObjectLiteral()->BuildBoilerplateDescription(isolate);
667 33675 : return;
668 : }
669 : DCHECK(IsRegExpLiteral());
670 : }
671 :
672 1718 : Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
673 12430 : Isolate* isolate) {
674 : Handle<FixedArray> raw_strings =
675 1718 : isolate->factory()->NewFixedArray(this->raw_strings()->length(), TENURED);
676 : bool raw_and_cooked_match = true;
677 9132 : for (int i = 0; i < raw_strings->length(); ++i) {
678 4660 : if (this->cooked_strings()->at(i) == nullptr ||
679 1812 : *this->raw_strings()->at(i)->string() !=
680 1812 : *this->cooked_strings()->at(i)->string()) {
681 : raw_and_cooked_match = false;
682 : }
683 8544 : raw_strings->set(i, *this->raw_strings()->at(i)->string());
684 : }
685 : Handle<FixedArray> cooked_strings = raw_strings;
686 1718 : if (!raw_and_cooked_match) {
687 : cooked_strings = isolate->factory()->NewFixedArray(
688 1176 : this->cooked_strings()->length(), TENURED);
689 6408 : for (int i = 0; i < cooked_strings->length(); ++i) {
690 2028 : if (this->cooked_strings()->at(i) != nullptr) {
691 2976 : cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
692 : } else {
693 2072 : cooked_strings->set(i, ReadOnlyRoots(isolate).undefined_value());
694 : }
695 : }
696 : }
697 : return isolate->factory()->NewTemplateObjectDescription(raw_strings,
698 1718 : cooked_strings);
699 : }
700 :
701 : static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
702 : // Add is not commutative due to potential for string addition.
703 262836 : return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
704 : op == Token::BIT_XOR;
705 : }
706 :
707 : // Check for the pattern: x + 1.
708 421255 : static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
709 : Expression** expr, Smi* literal) {
710 421255 : if (right->IsSmiLiteral()) {
711 119978 : *expr = left;
712 359928 : *literal = right->AsLiteral()->AsSmiLiteral();
713 119975 : return true;
714 : }
715 : return false;
716 : }
717 :
718 356821 : bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
719 262836 : Smi* literal) {
720 619657 : return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
721 64444 : (IsCommutativeOperationWithSmiLiteral(op()) &&
722 421270 : MatchSmiLiteralOperation(right_, left_, subexpr, literal));
723 : }
724 :
725 1654521 : static bool IsTypeof(Expression* expr) {
726 1801346 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
727 1801362 : return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
728 : }
729 :
730 : // Check for the pattern: typeof <expression> equals <string literal>.
731 1654520 : static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
732 : Expression* right, Expression** expr,
733 : Literal** literal) {
734 1753910 : if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
735 198780 : *expr = left->AsUnaryOperation()->expression();
736 198779 : *literal = right->AsLiteral();
737 99389 : return true;
738 : }
739 : return false;
740 : }
741 :
742 876936 : bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
743 1654552 : Literal** literal) {
744 2531505 : return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
745 2432187 : MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
746 : }
747 :
748 :
749 1554150 : static bool IsVoidOfLiteral(Expression* expr) {
750 1603324 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
751 1603325 : return maybe_unary != nullptr && maybe_unary->op() == Token::VOID &&
752 1554151 : maybe_unary->expression()->IsLiteral();
753 : }
754 :
755 :
756 : // Check for the pattern: void <literal> equals <expression> or
757 : // undefined equals <expression>
758 1554145 : static bool MatchLiteralCompareUndefined(Expression* left,
759 : Token::Value op,
760 : Expression* right,
761 : Expression** expr) {
762 1556072 : if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
763 1129 : *expr = right;
764 1129 : return true;
765 : }
766 1612349 : if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
767 59262 : *expr = right;
768 59262 : return true;
769 : }
770 : return false;
771 : }
772 :
773 2331700 : bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
774 2331700 : return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
775 2330769 : MatchLiteralCompareUndefined(right_, op(), left_, expr);
776 : }
777 :
778 : // Check for the pattern: null equals <expression>
779 : static bool MatchLiteralCompareNull(Expression* left,
780 : Token::Value op,
781 : Expression* right,
782 : Expression** expr) {
783 1439528 : if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
784 5069 : *expr = right;
785 : return true;
786 : }
787 : return false;
788 : }
789 :
790 2150789 : bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
791 2867953 : return MatchLiteralCompareNull(left_, op(), right_, expr) ||
792 2150114 : MatchLiteralCompareNull(right_, op(), left_, expr);
793 : }
794 :
795 5109594 : Call::CallType Call::GetCallType() const {
796 9318622 : VariableProxy* proxy = expression()->AsVariableProxy();
797 5109656 : if (proxy != nullptr) {
798 4209028 : if (proxy->var()->IsUnallocated()) {
799 : return GLOBAL_CALL;
800 419419 : } else if (proxy->var()->IsLookupSlot()) {
801 : // Calls going through 'with' always use VariableMode::kDynamic rather
802 : // than VariableMode::kDynamicLocal or VariableMode::kDynamicGlobal.
803 : return proxy->var()->mode() == VariableMode::kDynamic ? WITH_CALL
804 177479 : : OTHER_CALL;
805 : }
806 : }
807 :
808 1142568 : if (expression()->IsSuperCallReference()) return SUPER_CALL;
809 :
810 790084 : Property* property = expression()->AsProperty();
811 1137322 : if (property != nullptr) {
812 : bool is_super = property->IsSuperAccess();
813 790084 : if (property->key()->IsPropertyName()) {
814 785475 : return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
815 : } else {
816 4592 : return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
817 : }
818 : }
819 :
820 347246 : if (expression()->IsResolvedProperty()) {
821 : return RESOLVED_PROPERTY_CALL;
822 : }
823 :
824 347246 : return OTHER_CALL;
825 : }
826 :
827 88853 : CaseClause::CaseClause(Zone* zone, Expression* label,
828 : const ScopedPtrList<Statement>& statements)
829 88853 : : label_(label), statements_(0, nullptr) {
830 88853 : statements.CopyTo(&statements_, zone);
831 88853 : }
832 :
833 9528949 : bool Literal::IsPropertyName() const {
834 9528949 : if (type() != kString) return false;
835 : uint32_t index;
836 8539640 : return !string_->AsArrayIndex(&index);
837 : }
838 :
839 4254580 : bool Literal::ToUint32(uint32_t* value) const {
840 4254580 : switch (type()) {
841 : case kString:
842 2687900 : return string_->AsArrayIndex(value);
843 : case kSmi:
844 1566633 : if (smi_ < 0) return false;
845 1566633 : *value = static_cast<uint32_t>(smi_);
846 1566633 : return true;
847 : case kHeapNumber:
848 130 : return DoubleToUint32IfEqualToSelf(AsNumber(), value);
849 : default:
850 : return false;
851 : }
852 : }
853 :
854 266669 : bool Literal::AsArrayIndex(uint32_t* value) const {
855 4254608 : return ToUint32(value) && *value != kMaxUInt32;
856 : }
857 :
858 8671275 : Handle<Object> Literal::BuildValue(Isolate* isolate) const {
859 8671275 : switch (type()) {
860 : case kSmi:
861 13257068 : return handle(Smi::FromInt(smi_), isolate);
862 : case kHeapNumber:
863 408016 : return isolate->factory()->NewNumber(number_, TENURED);
864 : case kString:
865 520278 : return string_->string();
866 : case kSymbol:
867 0 : return isolate->factory()->home_object_symbol();
868 : case kBoolean:
869 39796 : return isolate->factory()->ToBoolean(boolean_);
870 : case kNull:
871 2351 : return isolate->factory()->null_value();
872 : case kUndefined:
873 261 : return isolate->factory()->undefined_value();
874 : case kTheHole:
875 1069551 : return isolate->factory()->the_hole_value();
876 : case kBigInt:
877 : // This should never fail: the parser will never create a BigInt
878 : // literal that cannot be allocated.
879 4976 : return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
880 : }
881 0 : UNREACHABLE();
882 : }
883 :
884 379695 : bool Literal::ToBooleanIsTrue() const {
885 379695 : switch (type()) {
886 : case kSmi:
887 48489 : return smi_ != 0;
888 : case kHeapNumber:
889 172 : return DoubleToBoolean(number_);
890 : case kString:
891 876 : return !string_->IsEmpty();
892 : case kNull:
893 : case kUndefined:
894 : return false;
895 : case kBoolean:
896 330532 : return boolean_;
897 : case kBigInt: {
898 : const char* bigint_str = bigint_.c_str();
899 14 : size_t length = strlen(bigint_str);
900 : DCHECK_GT(length, 0);
901 14 : if (length == 1 && bigint_str[0] == '0') return false;
902 : // Skip over any radix prefix; BigInts with length > 1 only
903 : // begin with zero if they include a radix.
904 47 : for (size_t i = (bigint_str[0] == '0') ? 2 : 0; i < length; ++i) {
905 41 : if (bigint_str[i] != '0') return true;
906 : }
907 : return false;
908 : }
909 : case kSymbol:
910 0 : return true;
911 : case kTheHole:
912 0 : UNREACHABLE();
913 : }
914 0 : UNREACHABLE();
915 : }
916 :
917 4524411 : uint32_t Literal::Hash() {
918 1538482 : return IsString() ? AsRawString()->Hash()
919 7419306 : : ComputeLongHash(double_to_uint64(AsNumber()));
920 : }
921 :
922 :
923 : // static
924 76461 : bool Literal::Match(void* a, void* b) {
925 75214 : Literal* x = static_cast<Literal*>(a);
926 75214 : Literal* y = static_cast<Literal*>(b);
927 150424 : return (x->IsString() && y->IsString() &&
928 77743 : x->AsRawString() == y->AsRawString()) ||
929 1282 : (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
930 : }
931 :
932 6563571 : Literal* AstNodeFactory::NewNumberLiteral(double number, int pos) {
933 : int int_value;
934 3677317 : if (DoubleToSmiInteger(number, &int_value)) {
935 2886210 : return NewSmiLiteral(int_value, pos);
936 : }
937 1582120 : return new (zone_) Literal(number, pos);
938 : }
939 :
940 0 : const char* CallRuntime::debug_name() {
941 : #ifdef DEBUG
942 : return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
943 : : function_->name;
944 : #else
945 0 : return is_jsruntime() ? "(context function)" : function_->name;
946 : #endif // DEBUG
947 : }
948 :
949 : #define RETURN_LABELS(NodeType) \
950 : case k##NodeType: \
951 : return static_cast<const NodeType*>(this)->labels();
952 :
953 24591 : ZonePtrList<const AstRawString>* BreakableStatement::labels() const {
954 48716 : switch (node_type()) {
955 21057 : BREAKABLE_NODE_LIST(RETURN_LABELS)
956 255 : ITERATION_NODE_LIST(RETURN_LABELS)
957 : default:
958 0 : UNREACHABLE();
959 : }
960 : }
961 :
962 : #undef RETURN_LABELS
963 :
964 : } // namespace internal
965 178779 : } // namespace v8
|