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 :
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 35634 : IterationStatement* AstNode::AsIterationStatement() {
66 35634 : switch (node_type()) {
67 352 : ITERATION_NODE_LIST(RETURN_NODE);
68 : default:
69 : return nullptr;
70 : }
71 : }
72 :
73 21373938 : MaterializedLiteral* AstNode::AsMaterializedLiteral() {
74 22707965 : switch (node_type()) {
75 64048 : LITERAL_NODE_LIST(RETURN_NODE);
76 : default:
77 : return nullptr;
78 : }
79 : }
80 :
81 : #undef RETURN_NODE
82 :
83 811493 : bool Expression::IsSmiLiteral() const {
84 1547610 : return IsLiteral() && AsLiteral()->type() == Literal::kSmi;
85 : }
86 :
87 2747635 : bool Expression::IsNumberLiteral() const {
88 4560463 : return IsLiteral() && AsLiteral()->IsNumber();
89 : }
90 :
91 389558 : bool Expression::IsStringLiteral() const {
92 1071204 : return IsLiteral() && AsLiteral()->type() == Literal::kString;
93 : }
94 :
95 9244522 : bool Expression::IsPropertyName() const {
96 16628024 : return IsLiteral() && AsLiteral()->IsPropertyName();
97 : }
98 :
99 1429443 : bool Expression::IsNullLiteral() const {
100 2214948 : return IsLiteral() && AsLiteral()->type() == Literal::kNull;
101 : }
102 :
103 41241 : bool Expression::IsTheHoleLiteral() const {
104 43569 : return IsLiteral() && AsLiteral()->type() == Literal::kTheHole;
105 : }
106 :
107 17101624 : bool Expression::IsCompileTimeValue() {
108 17101769 : if (IsLiteral()) return true;
109 : MaterializedLiteral* literal = AsMaterializedLiteral();
110 1334027 : if (literal == nullptr) return false;
111 229032 : return literal->IsSimple();
112 : }
113 :
114 1494131 : bool Expression::IsUndefinedLiteral() const {
115 2289867 : if (IsLiteral() && AsLiteral()->type() == Literal::kUndefined) return true;
116 :
117 2110279 : const VariableProxy* var_proxy = AsVariableProxy();
118 1484081 : if (var_proxy == nullptr) return false;
119 : Variable* var = var_proxy->var();
120 : // The global identifier "undefined" is immutable. Everything
121 : // else could be reassigned.
122 1426800 : return var != nullptr && var->IsUnallocated() &&
123 800625 : var_proxy->raw_name()->IsOneByteEqualTo("undefined");
124 : }
125 :
126 918013 : bool Expression::ToBooleanIsTrue() const {
127 942239 : return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
128 : }
129 :
130 904125 : bool Expression::ToBooleanIsFalse() const {
131 937746 : return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
132 : }
133 :
134 0 : bool Expression::IsValidReferenceExpression() const {
135 0 : return IsProperty() ||
136 0 : (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
137 : }
138 :
139 11981295 : bool Expression::IsAnonymousFunctionDefinition() const {
140 1597016 : return (IsFunctionLiteral() &&
141 23604724 : AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
142 3673 : (IsClassLiteral() &&
143 11985007 : AsClassLiteral()->IsAnonymousFunctionDefinition());
144 : }
145 :
146 11621005 : bool Expression::IsConciseMethodDefinition() const {
147 12859945 : return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
148 : }
149 :
150 11261336 : bool Expression::IsAccessorFunctionDefinition() const {
151 12140621 : return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
152 : }
153 :
154 36551 : bool Statement::IsJump() const {
155 48064 : switch (node_type()) {
156 : #define JUMP_NODE_LIST(V) \
157 : V(Block) \
158 : V(ExpressionStatement) \
159 : V(ContinueStatement) \
160 : V(BreakStatement) \
161 : V(ReturnStatement) \
162 : V(IfStatement)
163 : #define GENERATE_CASE(Node) \
164 : case k##Node: \
165 : return static_cast<const Node*>(this)->IsJump();
166 15905 : JUMP_NODE_LIST(GENERATE_CASE)
167 : #undef GENERATE_CASE
168 : #undef JUMP_NODE_LIST
169 : default:
170 1764 : return false;
171 : }
172 : }
173 :
174 5769178 : VariableProxy::VariableProxy(Variable* var, int start_position)
175 : : Expression(start_position, kVariableProxy),
176 : raw_name_(var->raw_name()),
177 2884589 : next_unresolved_(nullptr) {
178 : bit_field_ |= IsThisField::encode(var->is_this()) |
179 : IsAssignedField::encode(false) |
180 : IsResolvedField::encode(false) |
181 2884589 : HoleCheckModeField::encode(HoleCheckMode::kElided);
182 : BindTo(var);
183 2884589 : }
184 :
185 5679831 : VariableProxy::VariableProxy(const VariableProxy* copy_from)
186 : : Expression(copy_from->position(), kVariableProxy),
187 11359662 : next_unresolved_(nullptr) {
188 5679831 : bit_field_ = copy_from->bit_field_;
189 : DCHECK(!copy_from->is_resolved());
190 5679831 : raw_name_ = copy_from->raw_name_;
191 5679831 : }
192 :
193 66705297 : void VariableProxy::BindTo(Variable* var) {
194 : DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name());
195 : set_var(var);
196 : set_is_resolved();
197 : var->set_is_used();
198 34794943 : if (is_assigned()) var->set_maybe_assigned();
199 31910354 : }
200 :
201 14351337 : Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
202 : Expression* value, int pos)
203 14351337 : : Expression(pos, node_type), target_(target), value_(value) {
204 14351337 : bit_field_ |= TokenField::encode(op);
205 14351337 : }
206 :
207 1424480 : void FunctionLiteral::set_inferred_name(Handle<String> inferred_name) {
208 : DCHECK(!inferred_name.is_null());
209 712240 : inferred_name_ = inferred_name;
210 : DCHECK(raw_inferred_name_ == nullptr || raw_inferred_name_->IsEmpty());
211 712240 : raw_inferred_name_ = nullptr;
212 : scope()->set_has_inferred_function_name(true);
213 712240 : }
214 :
215 475095 : void FunctionLiteral::set_raw_inferred_name(
216 475095 : const AstConsString* raw_inferred_name) {
217 : DCHECK_NOT_NULL(raw_inferred_name);
218 475095 : raw_inferred_name_ = raw_inferred_name;
219 : DCHECK(inferred_name_.is_null());
220 475095 : inferred_name_ = Handle<String>();
221 : scope()->set_has_inferred_function_name(true);
222 475095 : }
223 :
224 6418718 : bool FunctionLiteral::ShouldEagerCompile() const {
225 6418718 : return scope()->ShouldEagerCompile();
226 : }
227 :
228 722935 : void FunctionLiteral::SetShouldEagerCompile() {
229 722935 : scope()->set_should_eager_compile();
230 722960 : }
231 :
232 3564345 : bool FunctionLiteral::AllowsLazyCompilation() {
233 3564345 : return scope()->AllowsLazyCompilation();
234 : }
235 :
236 0 : Handle<String> FunctionLiteral::name(Isolate* isolate) const {
237 0 : return raw_name_ ? raw_name_->string() : isolate->factory()->empty_string();
238 : }
239 :
240 10813691 : int FunctionLiteral::start_position() const {
241 10813691 : return scope()->start_position();
242 : }
243 :
244 :
245 5125739 : int FunctionLiteral::end_position() const {
246 5125739 : return scope()->end_position();
247 : }
248 :
249 :
250 4906811 : LanguageMode FunctionLiteral::language_mode() const {
251 4906811 : return scope()->language_mode();
252 : }
253 :
254 12181914 : FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
255 :
256 296601 : bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
257 593214 : if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
258 : DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
259 306040 : return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
260 : }
261 :
262 29 : std::unique_ptr<char[]> FunctionLiteral::GetDebugName() const {
263 : const AstConsString* cons_string;
264 29 : if (raw_name_ != nullptr && !raw_name_->IsEmpty()) {
265 : cons_string = raw_name_;
266 8 : } else if (raw_inferred_name_ != nullptr && !raw_inferred_name_->IsEmpty()) {
267 : cons_string = raw_inferred_name_;
268 8 : } else if (!inferred_name_.is_null()) {
269 : AllowHandleDereference allow_deref;
270 8 : return inferred_name_->ToCString();
271 : } else {
272 0 : char* empty_str = new char[1];
273 0 : empty_str[0] = 0;
274 : return std::unique_ptr<char[]>(empty_str);
275 : }
276 :
277 : // TODO(rmcilroy): Deal with two-character strings.
278 : std::vector<char> result_vec;
279 21 : std::forward_list<const AstRawString*> strings = cons_string->ToRawStrings();
280 63 : for (const AstRawString* string : strings) {
281 21 : if (!string->is_one_byte()) break;
282 415 : for (int i = 0; i < string->length(); i++) {
283 394 : result_vec.push_back(string->raw_data()[i]);
284 : }
285 : }
286 42 : std::unique_ptr<char[]> result(new char[result_vec.size() + 1]);
287 21 : memcpy(result.get(), result_vec.data(), result_vec.size());
288 42 : result[result_vec.size()] = '\0';
289 : return result;
290 : }
291 :
292 130680 : ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
293 : Kind kind, bool is_computed_name)
294 : : LiteralProperty(key, value, is_computed_name),
295 : kind_(kind),
296 130680 : emit_store_(true) {}
297 :
298 4353660 : ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
299 : Expression* key, Expression* value,
300 : bool is_computed_name)
301 2907827 : : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
302 7247632 : if (!is_computed_name && key->AsLiteral()->IsString() &&
303 1445833 : key->AsLiteral()->AsRawString() == ast_value_factory->proto_string()) {
304 6588 : kind_ = PROTOTYPE;
305 2901252 : } else if (value_->AsMaterializedLiteral() != nullptr) {
306 60877 : kind_ = MATERIALIZED_LITERAL;
307 2840392 : } else if (value_->IsLiteral()) {
308 1854093 : kind_ = CONSTANT;
309 : } else {
310 986299 : kind_ = COMPUTED;
311 : }
312 2907857 : }
313 :
314 3394363 : bool LiteralProperty::NeedsSetFunctionName() const {
315 3423771 : return is_computed_name() && (value_->IsAnonymousFunctionDefinition() ||
316 51933 : value_->IsConciseMethodDefinition() ||
317 3416890 : value_->IsAccessorFunctionDefinition());
318 : }
319 :
320 437647 : ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
321 : Kind kind, bool is_static,
322 : bool is_computed_name,
323 : bool is_private)
324 : : LiteralProperty(key, value, is_computed_name),
325 : kind_(kind),
326 : is_static_(is_static),
327 : is_private_(is_private),
328 437647 : private_or_computed_name_var_(nullptr) {}
329 :
330 2017000 : bool ObjectLiteral::Property::IsCompileTimeValue() const {
331 2017000 : return kind_ == CONSTANT ||
332 44993 : (kind_ == MATERIALIZED_LITERAL && value_->IsCompileTimeValue());
333 : }
334 :
335 :
336 0 : void ObjectLiteral::Property::set_emit_store(bool emit_store) {
337 3384 : emit_store_ = emit_store;
338 0 : }
339 :
340 251291 : bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
341 :
342 580367 : void ObjectLiteral::CalculateEmitStore(Zone* zone) {
343 : const auto GETTER = ObjectLiteral::Property::GETTER;
344 : const auto SETTER = ObjectLiteral::Property::SETTER;
345 :
346 : ZoneAllocationPolicy allocator(zone);
347 :
348 : CustomMatcherZoneHashMap table(
349 : Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
350 3590903 : for (int i = properties()->length() - 1; i >= 0; i--) {
351 3014577 : ObjectLiteral::Property* property = properties()->at(i);
352 3010476 : if (property->is_computed_name()) continue;
353 2989531 : if (property->IsPrototype()) continue;
354 2982916 : Literal* literal = property->key()->AsLiteral();
355 : DCHECK(!literal->IsNullLiteral());
356 :
357 2982955 : uint32_t hash = literal->Hash();
358 5965843 : ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
359 2987029 : if (entry->value == nullptr) {
360 2978827 : entry->value = property;
361 : } else {
362 : // We already have a later definition of this property, so we don't need
363 : // to emit a store for the current one.
364 : //
365 : // There are two subtleties here.
366 : //
367 : // (1) Emitting a store might actually be incorrect. For example, in {get
368 : // foo() {}, foo: 42}, the getter store would override the data property
369 : // (which, being a non-computed compile-time valued property, is already
370 : // part of the initial literal object.
371 : //
372 : // (2) If the later definition is an accessor (say, a getter), and the
373 : // current definition is a complementary accessor (here, a setter), then
374 : // we still must emit a store for the current definition.
375 :
376 : auto later_kind =
377 : static_cast<ObjectLiteral::Property*>(entry->value)->kind();
378 : bool complementary_accessors =
379 4101 : (property->kind() == GETTER && later_kind == SETTER) ||
380 204 : (property->kind() == SETTER && later_kind == GETTER);
381 4101 : if (!complementary_accessors) {
382 : property->set_emit_store(false);
383 3384 : if (later_kind == GETTER || later_kind == SETTER) {
384 1066 : entry->value = property;
385 : }
386 : }
387 : }
388 : }
389 580427 : }
390 :
391 2137 : void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
392 : // We still check for __proto__:null after computed property names.
393 5240 : for (; i < properties()->length(); i++) {
394 6215 : if (properties()->at(i)->IsNullPrototype()) {
395 : set_has_null_protoype(true);
396 : break;
397 : }
398 : }
399 2138 : }
400 :
401 266692 : int ObjectLiteral::InitDepthAndFlags() {
402 285132 : if (is_initialized()) return depth();
403 : bool is_simple = true;
404 : bool has_seen_prototype = false;
405 : bool needs_initial_allocation_site = false;
406 : int depth_acc = 1;
407 : uint32_t nof_properties = 0;
408 : uint32_t elements = 0;
409 : uint32_t max_element_index = 0;
410 2050702 : for (int i = 0; i < properties()->length(); i++) {
411 2052723 : ObjectLiteral::Property* property = properties()->at(i);
412 2052723 : if (property->IsPrototype()) {
413 : has_seen_prototype = true;
414 : // __proto__:null has no side-effects and is set directly on the
415 : // boilerplate.
416 4089 : if (property->IsNullPrototype()) {
417 : set_has_null_protoype(true);
418 4089 : continue;
419 : }
420 : DCHECK(!has_null_prototype());
421 : is_simple = false;
422 : continue;
423 : }
424 2048654 : if (nof_properties == boilerplate_properties_) {
425 : DCHECK(property->is_computed_name());
426 : is_simple = false;
427 2170 : if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
428 2170 : break;
429 : }
430 : DCHECK(!property->is_computed_name());
431 :
432 4092920 : MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
433 2046484 : if (literal != nullptr) {
434 46601 : int subliteral_depth = literal->InitDepthAndFlags() + 1;
435 46603 : if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
436 46603 : needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
437 : }
438 :
439 2046486 : Literal* key = property->key()->AsLiteral();
440 : Expression* value = property->value();
441 :
442 2046436 : bool is_compile_time_value = value->IsCompileTimeValue();
443 2046565 : is_simple = is_simple && is_compile_time_value;
444 :
445 : // Keep track of the number of elements in the object literal and
446 : // the largest element index. If the largest element index is
447 : // much larger than the number of elements, creating an object
448 : // literal with fast elements will be a waste of space.
449 2046565 : uint32_t element_index = 0;
450 2046613 : if (key->AsArrayIndex(&element_index)) {
451 785842 : max_element_index = Max(element_index, max_element_index);
452 785842 : elements++;
453 : } else {
454 : DCHECK(key->IsPropertyName());
455 : }
456 :
457 2046613 : nof_properties++;
458 : }
459 :
460 : set_depth(depth_acc);
461 : set_is_simple(is_simple);
462 : set_needs_initial_allocation_site(needs_initial_allocation_site);
463 248401 : set_has_elements(elements > 0);
464 248968 : set_fast_elements((max_element_index <= 32) ||
465 567 : ((2 * elements) >= max_element_index));
466 248401 : return depth_acc;
467 : }
468 :
469 207518 : void ObjectLiteral::BuildBoilerplateDescription(Isolate* isolate) {
470 415047 : if (!boilerplate_description_.is_null()) return;
471 :
472 : int index_keys = 0;
473 : bool has_seen_proto = false;
474 1970177 : for (int i = 0; i < properties()->length(); i++) {
475 1970170 : ObjectLiteral::Property* property = properties()->at(i);
476 1970170 : if (property->IsPrototype()) {
477 : has_seen_proto = true;
478 : continue;
479 : }
480 1966895 : if (property->is_computed_name()) {
481 : continue;
482 : }
483 :
484 1966345 : Literal* key = property->key()->AsLiteral();
485 :
486 1966352 : if (!key->IsPropertyName()) {
487 784254 : index_keys++;
488 : }
489 : }
490 :
491 : Handle<ObjectBoilerplateDescription> boilerplate_description =
492 : isolate->factory()->NewObjectBoilerplateDescription(
493 : boilerplate_properties_, properties()->length(), index_keys,
494 205234 : has_seen_proto);
495 :
496 : int position = 0;
497 2174576 : for (int i = 0; i < properties()->length(); i++) {
498 1969765 : ObjectLiteral::Property* property = properties()->at(i);
499 1973040 : if (property->IsPrototype()) continue;
500 :
501 1966490 : if (static_cast<uint32_t>(position) == boilerplate_properties_) {
502 : DCHECK(property->is_computed_name());
503 425 : break;
504 : }
505 : DCHECK(!property->is_computed_name());
506 :
507 3932128 : MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
508 1966065 : if (m_literal != nullptr) {
509 45313 : m_literal->BuildConstants(isolate);
510 : }
511 :
512 : // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
513 : // value for COMPUTED properties, the real value is filled in at
514 : // runtime. The enumeration order is maintained.
515 3148015 : Literal* key_literal = property->key()->AsLiteral();
516 1966064 : uint32_t element_index = 0;
517 : Handle<Object> key =
518 : key_literal->AsArrayIndex(&element_index)
519 784114 : ? isolate->factory()->NewNumberFromUint(element_index)
520 3932128 : : Handle<Object>::cast(key_literal->AsRawPropertyName()->string());
521 :
522 1966063 : Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
523 :
524 : // Add name, value pair to the fixed array.
525 3932126 : boilerplate_description->set_key_value(position++, *key, *value);
526 : }
527 :
528 : boilerplate_description->set_flags(EncodeLiteralType());
529 :
530 205238 : boilerplate_description_ = boilerplate_description;
531 : }
532 :
533 384722 : bool ObjectLiteral::IsFastCloningSupported() const {
534 : // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
535 : // literals don't support copy-on-write (COW) elements for now.
536 : // TODO(mvstanton): make object literals support COW elements.
537 586182 : return fast_elements() && is_shallow() &&
538 : properties_count() <=
539 201833 : ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
540 : }
541 :
542 411200 : int ArrayLiteral::InitDepthAndFlags() {
543 416086 : if (is_initialized()) return depth();
544 :
545 : int constants_length =
546 406314 : first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
547 :
548 : // Fill in the literals.
549 406314 : bool is_simple = first_spread_index_ < 0;
550 : int depth_acc = 1;
551 : int array_index = 0;
552 7688246 : for (; array_index < constants_length; array_index++) {
553 7281918 : Expression* element = values()->at(array_index);
554 : MaterializedLiteral* literal = element->AsMaterializedLiteral();
555 7281918 : if (literal != nullptr) {
556 32526 : int subliteral_depth = literal->InitDepthAndFlags() + 1;
557 32527 : if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
558 : }
559 :
560 7281919 : if (!element->IsCompileTimeValue()) {
561 : is_simple = false;
562 : }
563 : }
564 :
565 : set_depth(depth_acc);
566 : set_is_simple(is_simple);
567 : // Array literals always need an initial allocation site to properly track
568 : // elements transitions.
569 : set_needs_initial_allocation_site(true);
570 406328 : return depth_acc;
571 : }
572 :
573 179302 : void ArrayLiteral::BuildBoilerplateDescription(Isolate* isolate) {
574 179302 : if (!boilerplate_description_.is_null()) return;
575 :
576 : int constants_length =
577 179302 : first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
578 : ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
579 : Handle<FixedArray> fixed_array =
580 179302 : isolate->factory()->NewFixedArrayWithHoles(constants_length);
581 :
582 : // Fill in the literals.
583 : bool is_holey = false;
584 : int array_index = 0;
585 7357524 : for (; array_index < constants_length; array_index++) {
586 7178219 : Expression* element = values()->at(array_index);
587 : DCHECK(!element->IsSpread());
588 : MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
589 7178219 : if (m_literal != nullptr) {
590 29758 : m_literal->BuildConstants(isolate);
591 : }
592 :
593 : // New handle scope here, needs to be after BuildContants().
594 : HandleScope scope(isolate);
595 7178219 : Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
596 14356436 : if (boilerplate_value->IsTheHole(isolate)) {
597 : is_holey = true;
598 : continue;
599 : }
600 :
601 12217350 : if (boilerplate_value->IsUninitialized(isolate)) {
602 : boilerplate_value = handle(Smi::kZero, isolate);
603 : }
604 :
605 : kind = GetMoreGeneralElementsKind(kind,
606 12217345 : boilerplate_value->OptimalElementsKind());
607 6108673 : fixed_array->set(array_index, *boilerplate_value);
608 : }
609 :
610 179305 : if (is_holey) kind = GetHoleyElementsKind(kind);
611 :
612 : // Simple and shallow arrays can be lazily copied, we transform the
613 : // elements array to a copy-on-write array.
614 436064 : if (is_simple() && depth() == 1 && array_index > 0 &&
615 : IsSmiOrObjectElementsKind(kind)) {
616 56966 : fixed_array->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
617 : }
618 :
619 : Handle<FixedArrayBase> elements = fixed_array;
620 179305 : if (IsDoubleElementsKind(kind)) {
621 : ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
622 3496 : elements = isolate->factory()->NewFixedDoubleArray(constants_length);
623 : // We are copying from non-fast-double to fast-double.
624 : ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
625 : accessor->CopyElements(isolate, fixed_array, from_kind, elements,
626 6992 : constants_length);
627 : }
628 :
629 : boilerplate_description_ =
630 179305 : isolate->factory()->NewArrayBoilerplateDescription(kind, elements);
631 : }
632 :
633 377452 : bool ArrayLiteral::IsFastCloningSupported() const {
634 747675 : return depth() <= 1 &&
635 370223 : values_.length() <=
636 377452 : ConstructorBuiltins::kMaximumClonedShallowArrayElements;
637 : }
638 :
639 229030 : bool MaterializedLiteral::IsSimple() const {
640 408296 : if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
641 354009 : if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
642 : DCHECK(IsRegExpLiteral());
643 : return false;
644 : }
645 :
646 9144282 : Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
647 : Isolate* isolate) {
648 9144282 : if (expression->IsLiteral()) {
649 17304568 : return expression->AsLiteral()->BuildValue(isolate);
650 : }
651 491998 : if (expression->IsCompileTimeValue()) {
652 42261 : if (expression->IsObjectLiteral()) {
653 17389 : ObjectLiteral* object_literal = expression->AsObjectLiteral();
654 : DCHECK(object_literal->is_simple());
655 17389 : return object_literal->boilerplate_description();
656 : } else {
657 : DCHECK(expression->IsArrayLiteral());
658 24872 : ArrayLiteral* array_literal = expression->AsArrayLiteral();
659 : DCHECK(array_literal->is_simple());
660 24872 : return array_literal->boilerplate_description();
661 : }
662 : }
663 449737 : return isolate->factory()->uninitialized_value();
664 : }
665 :
666 79123 : int MaterializedLiteral::InitDepthAndFlags() {
667 110774 : if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
668 84247 : if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
669 : DCHECK(IsRegExpLiteral());
670 : return 1;
671 : }
672 :
673 46603 : bool MaterializedLiteral::NeedsInitialAllocationSite() {
674 46603 : if (IsArrayLiteral()) {
675 54090 : return AsArrayLiteral()->needs_initial_allocation_site();
676 : }
677 28573 : if (IsObjectLiteral()) {
678 54534 : return AsObjectLiteral()->needs_initial_allocation_site();
679 : }
680 : DCHECK(IsRegExpLiteral());
681 : return false;
682 : }
683 :
684 75069 : void MaterializedLiteral::BuildConstants(Isolate* isolate) {
685 75069 : if (IsArrayLiteral()) {
686 58574 : AsArrayLiteral()->BuildBoilerplateDescription(isolate);
687 29287 : return;
688 : }
689 45782 : if (IsObjectLiteral()) {
690 70214 : AsObjectLiteral()->BuildBoilerplateDescription(isolate);
691 35108 : return;
692 : }
693 : DCHECK(IsRegExpLiteral());
694 : }
695 :
696 1844 : Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
697 13156 : Isolate* isolate) {
698 : Handle<FixedArray> raw_strings =
699 1844 : isolate->factory()->NewFixedArray(this->raw_strings()->length(), TENURED);
700 : bool raw_and_cooked_match = true;
701 9730 : for (int i = 0; i < raw_strings->length(); ++i) {
702 4989 : if (this->cooked_strings()->at(i) == nullptr ||
703 1968 : *this->raw_strings()->at(i)->string() !=
704 1968 : *this->cooked_strings()->at(i)->string()) {
705 : raw_and_cooked_match = false;
706 : }
707 9063 : raw_strings->set(i, *this->raw_strings()->at(i)->string());
708 : }
709 : Handle<FixedArray> cooked_strings = raw_strings;
710 1844 : if (!raw_and_cooked_match) {
711 : cooked_strings = isolate->factory()->NewFixedArray(
712 1224 : this->cooked_strings()->length(), TENURED);
713 6604 : for (int i = 0; i < cooked_strings->length(); ++i) {
714 2078 : if (this->cooked_strings()->at(i) != nullptr) {
715 3075 : cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
716 : } else {
717 2106 : cooked_strings->set(i, ReadOnlyRoots(isolate).undefined_value());
718 : }
719 : }
720 : }
721 : return isolate->factory()->NewTemplateObjectDescription(raw_strings,
722 1844 : cooked_strings);
723 : }
724 :
725 : static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
726 : // Add is not commutative due to potential for string addition.
727 258971 : return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
728 : op == Token::BIT_XOR;
729 : }
730 :
731 : // Check for the pattern: x + 1.
732 424390 : static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
733 : Expression** expr, Smi* literal) {
734 424390 : if (right->IsSmiLiteral()) {
735 125949 : *expr = left;
736 377851 : *literal = right->AsLiteral()->AsSmiLiteral();
737 125951 : return true;
738 : }
739 : return false;
740 : }
741 :
742 357363 : bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
743 258971 : Smi* literal) {
744 616334 : return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
745 67037 : (IsCommutativeOperationWithSmiLiteral(op()) &&
746 424408 : MatchSmiLiteralOperation(right_, left_, subexpr, literal));
747 : }
748 :
749 1588314 : static bool IsTypeof(Expression* expr) {
750 1730419 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
751 1730423 : return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
752 : }
753 :
754 : // Check for the pattern: typeof <expression> equals <string literal>.
755 1588310 : static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
756 : Expression* right, Expression** expr,
757 : Literal** literal) {
758 1680902 : if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
759 185186 : *expr = left->AsUnaryOperation()->expression();
760 185185 : *literal = right->AsLiteral();
761 92592 : return true;
762 : }
763 : return false;
764 : }
765 :
766 840424 : bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
767 1588338 : Literal** literal) {
768 2428791 : return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
769 2336289 : MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
770 : }
771 :
772 :
773 1494685 : static bool IsVoidOfLiteral(Expression* expr) {
774 1550153 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
775 1550159 : return maybe_unary != nullptr && maybe_unary->op() == Token::VOID &&
776 1494691 : maybe_unary->expression()->IsLiteral();
777 : }
778 :
779 :
780 : // Check for the pattern: void <literal> equals <expression> or
781 : // undefined equals <expression>
782 1494684 : static bool MatchLiteralCompareUndefined(Expression* left,
783 : Token::Value op,
784 : Expression* right,
785 : Expression** expr) {
786 1500825 : if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
787 5342 : *expr = right;
788 5342 : return true;
789 : }
790 1523351 : if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
791 33940 : *expr = right;
792 33940 : return true;
793 : }
794 : return false;
795 : }
796 :
797 2242516 : bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
798 2242534 : return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
799 2241565 : MatchLiteralCompareUndefined(right_, op(), left_, expr);
800 : }
801 :
802 : // Check for the pattern: null equals <expression>
803 : static bool MatchLiteralCompareNull(Expression* left,
804 : Token::Value op,
805 : Expression* right,
806 : Expression** expr) {
807 1422261 : if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
808 4991 : *expr = right;
809 : return true;
810 : }
811 : return false;
812 : }
813 :
814 2124998 : bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
815 2833568 : return MatchLiteralCompareNull(left_, op(), right_, expr) ||
816 2124346 : MatchLiteralCompareNull(right_, op(), left_, expr);
817 : }
818 :
819 5167218 : Call::CallType Call::GetCallType() const {
820 9417092 : VariableProxy* proxy = expression()->AsVariableProxy();
821 5167336 : if (proxy != nullptr) {
822 4249874 : if (proxy->var()->IsUnallocated()) {
823 : return GLOBAL_CALL;
824 420558 : } else if (proxy->var()->IsLookupSlot()) {
825 : // Calls going through 'with' always use VariableMode::kDynamic rather
826 : // than VariableMode::kDynamicLocal or VariableMode::kDynamicGlobal.
827 : return proxy->var()->mode() == VariableMode::kDynamic ? WITH_CALL
828 191307 : : OTHER_CALL;
829 : }
830 : }
831 :
832 1146713 : if (expression()->IsSuperCallReference()) return SUPER_CALL;
833 :
834 805920 : Property* property = expression()->AsProperty();
835 1141561 : if (property != nullptr) {
836 : bool is_super = property->IsSuperAccess();
837 805920 : if (property->key()->IsPropertyName()) {
838 801320 : return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
839 : } else {
840 4558 : return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
841 : }
842 : }
843 :
844 335648 : if (expression()->IsResolvedProperty()) {
845 : return RESOLVED_PROPERTY_CALL;
846 : }
847 :
848 335645 : return OTHER_CALL;
849 : }
850 :
851 88679 : CaseClause::CaseClause(Zone* zone, Expression* label,
852 : const ScopedPtrList<Statement>& statements)
853 88679 : : label_(label), statements_(0, nullptr) {
854 88678 : statements.CopyTo(&statements_, zone);
855 88679 : }
856 :
857 9621024 : bool Literal::IsPropertyName() const {
858 9621024 : if (type() != kString) return false;
859 : uint32_t index;
860 8628777 : return !string_->AsArrayIndex(&index);
861 : }
862 :
863 4283470 : bool Literal::ToUint32(uint32_t* value) const {
864 4283470 : switch (type()) {
865 : case kString:
866 2714157 : return string_->AsArrayIndex(value);
867 : case kSmi:
868 1569250 : if (smi_ < 0) return false;
869 1569250 : *value = static_cast<uint32_t>(smi_);
870 1569250 : return true;
871 : case kHeapNumber:
872 130 : return DoubleToUint32IfEqualToSelf(AsNumber(), value);
873 : default:
874 : return false;
875 : }
876 : }
877 :
878 270879 : bool Literal::AsArrayIndex(uint32_t* value) const {
879 4283508 : return ToUint32(value) && *value != kMaxUInt32;
880 : }
881 :
882 8729603 : Handle<Object> Literal::BuildValue(Isolate* isolate) const {
883 8729603 : switch (type()) {
884 : case kSmi:
885 13362394 : return handle(Smi::FromInt(smi_), isolate);
886 : case kHeapNumber:
887 408726 : return isolate->factory()->NewNumber(number_, TENURED);
888 : case kString:
889 524799 : return string_->string();
890 : case kSymbol:
891 0 : return isolate->factory()->home_object_symbol();
892 : case kBoolean:
893 40075 : return isolate->factory()->ToBoolean(boolean_);
894 : case kNull:
895 2499 : return isolate->factory()->null_value();
896 : case kUndefined:
897 261 : return isolate->factory()->undefined_value();
898 : case kTheHole:
899 1069556 : return isolate->factory()->the_hole_value();
900 : case kBigInt:
901 : // This should never fail: the parser will never create a BigInt
902 : // literal that cannot be allocated.
903 4980 : return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
904 : }
905 0 : UNREACHABLE();
906 : }
907 :
908 371689 : bool Literal::ToBooleanIsTrue() const {
909 371689 : switch (type()) {
910 : case kSmi:
911 48517 : return smi_ != 0;
912 : case kHeapNumber:
913 172 : return DoubleToBoolean(number_);
914 : case kString:
915 886 : return !string_->IsEmpty();
916 : case kNull:
917 : case kUndefined:
918 : return false;
919 : case kBoolean:
920 322492 : return boolean_;
921 : case kBigInt: {
922 : const char* bigint_str = bigint_.c_str();
923 14 : size_t length = strlen(bigint_str);
924 : DCHECK_GT(length, 0);
925 14 : if (length == 1 && bigint_str[0] == '0') return false;
926 : // Skip over any radix prefix; BigInts with length > 1 only
927 : // begin with zero if they include a radix.
928 47 : for (size_t i = (bigint_str[0] == '0') ? 2 : 0; i < length; ++i) {
929 41 : if (bigint_str[i] != '0') return true;
930 : }
931 : return false;
932 : }
933 : case kSymbol:
934 0 : return true;
935 : case kTheHole:
936 0 : UNREACHABLE();
937 : }
938 0 : UNREACHABLE();
939 : }
940 :
941 4527756 : uint32_t Literal::Hash() {
942 1539505 : return IsString() ? AsRawString()->Hash()
943 7425248 : : ComputeLongHash(double_to_uint64(AsNumber()));
944 : }
945 :
946 :
947 : // static
948 77131 : bool Literal::Match(void* a, void* b) {
949 75793 : Literal* x = static_cast<Literal*>(a);
950 75793 : Literal* y = static_cast<Literal*>(b);
951 151581 : return (x->IsString() && y->IsString() &&
952 78482 : x->AsRawString() == y->AsRawString()) ||
953 1345 : (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
954 : }
955 :
956 6702510 : Literal* AstNodeFactory::NewNumberLiteral(double number, int pos) {
957 : int int_value;
958 3749051 : if (DoubleToSmiInteger(number, &int_value)) {
959 2953410 : return NewSmiLiteral(int_value, pos);
960 : }
961 1591171 : return new (zone_) Literal(number, pos);
962 : }
963 :
964 0 : const char* CallRuntime::debug_name() {
965 : #ifdef DEBUG
966 : return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
967 : : function_->name;
968 : #else
969 0 : return is_jsruntime() ? "(context function)" : function_->name;
970 : #endif // DEBUG
971 : }
972 :
973 : #define RETURN_LABELS(NodeType) \
974 : case k##NodeType: \
975 : return static_cast<const NodeType*>(this)->labels();
976 :
977 24774 : ZonePtrList<const AstRawString>* BreakableStatement::labels() const {
978 49052 : switch (node_type()) {
979 21194 : BREAKABLE_NODE_LIST(RETURN_LABELS)
980 257 : ITERATION_NODE_LIST(RETURN_LABELS)
981 : default:
982 0 : UNREACHABLE();
983 : }
984 : }
985 :
986 : #undef RETURN_LABELS
987 :
988 : } // namespace internal
989 183867 : } // namespace v8
|