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 34478 : IterationStatement* AstNode::AsIterationStatement() {
67 34478 : switch (node_type()) {
68 345 : ITERATION_NODE_LIST(RETURN_NODE);
69 : default:
70 : return nullptr;
71 : }
72 : }
73 :
74 0 : MaterializedLiteral* AstNode::AsMaterializedLiteral() {
75 20935343 : switch (node_type()) {
76 63973 : LITERAL_NODE_LIST(RETURN_NODE);
77 : default:
78 : return nullptr;
79 : }
80 : }
81 :
82 : #undef RETURN_NODE
83 :
84 426545 : bool Expression::IsSmiLiteral() const {
85 1252652 : return IsLiteral() && AsLiteral()->type() == Literal::kSmi;
86 : }
87 :
88 2829122 : bool Expression::IsNumberLiteral() const {
89 4662171 : return IsLiteral() && AsLiteral()->IsNumber();
90 : }
91 :
92 255142 : bool Expression::IsStringLiteral() const {
93 746925 : return IsLiteral() && AsLiteral()->type() == Literal::kString;
94 : }
95 :
96 9397728 : bool Expression::IsPropertyName() const {
97 16920779 : return IsLiteral() && AsLiteral()->IsPropertyName();
98 : }
99 :
100 8947 : bool Expression::IsNullLiteral() const {
101 1877950 : return IsLiteral() && AsLiteral()->type() == Literal::kNull;
102 : }
103 :
104 5170 : bool Expression::IsTheHoleLiteral() const {
105 5963 : return IsLiteral() && AsLiteral()->type() == Literal::kTheHole;
106 : }
107 :
108 15292826 : bool Expression::IsCompileTimeValue() {
109 15292826 : if (IsLiteral()) return true;
110 : MaterializedLiteral* literal = AsMaterializedLiteral();
111 1380352 : if (literal == nullptr) return false;
112 224934 : return literal->IsSimple();
113 : }
114 :
115 1589933 : bool Expression::IsUndefinedLiteral() const {
116 1995032 : if (IsLiteral() && AsLiteral()->type() == Literal::kUndefined) return true;
117 :
118 1580671 : const VariableProxy* var_proxy = AsVariableProxy();
119 1580671 : 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 1600173 : return var != nullptr && var->IsUnallocated() &&
124 207534 : var_proxy->raw_name()->IsOneByteEqualTo("undefined");
125 : }
126 :
127 966556 : bool Expression::ToBooleanIsTrue() const {
128 989390 : return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
129 : }
130 :
131 951296 : bool Expression::ToBooleanIsFalse() const {
132 983504 : return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
133 : }
134 :
135 0 : bool Expression::IsValidReferenceExpression() const {
136 0 : return IsProperty() ||
137 0 : (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
138 : }
139 :
140 11983321 : bool Expression::IsAnonymousFunctionDefinition() const {
141 1651266 : return (IsFunctionLiteral() &&
142 23616666 : AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
143 3867 : (IsClassLiteral() &&
144 11987188 : AsClassLiteral()->IsAnonymousFunctionDefinition());
145 : }
146 :
147 11601267 : bool Expression::IsConciseMethodDefinition() const {
148 12932012 : return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
149 : }
150 :
151 11231189 : bool Expression::IsAccessorFunctionDefinition() const {
152 12177846 : return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
153 : }
154 :
155 2930625 : VariableProxy::VariableProxy(Variable* var, int start_position)
156 : : Expression(start_position, kVariableProxy),
157 : raw_name_(var->raw_name()),
158 2930625 : next_unresolved_(nullptr) {
159 : DCHECK(!var->is_this());
160 : bit_field_ |= IsAssignedField::encode(false) |
161 : IsResolvedField::encode(false) |
162 2930625 : HoleCheckModeField::encode(HoleCheckMode::kElided);
163 : BindTo(var);
164 2930625 : }
165 :
166 6655837 : VariableProxy::VariableProxy(const VariableProxy* copy_from)
167 : : Expression(copy_from->position(), kVariableProxy),
168 6655837 : next_unresolved_(nullptr) {
169 6655837 : bit_field_ = copy_from->bit_field_;
170 : DCHECK(!copy_from->is_resolved());
171 6655837 : raw_name_ = copy_from->raw_name_;
172 6655837 : }
173 :
174 39781550 : 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 42712175 : if (is_assigned()) var->set_maybe_assigned();
180 39781550 : }
181 :
182 14333264 : Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
183 : Expression* value, int pos)
184 14333264 : : Expression(pos, node_type), target_(target), value_(value) {
185 14333264 : bit_field_ |= TokenField::encode(op);
186 14333264 : }
187 :
188 714954 : void FunctionLiteral::set_inferred_name(Handle<String> inferred_name) {
189 : DCHECK(!inferred_name.is_null());
190 714954 : inferred_name_ = inferred_name;
191 : DCHECK(raw_inferred_name_ == nullptr || raw_inferred_name_->IsEmpty());
192 714954 : raw_inferred_name_ = nullptr;
193 : scope()->set_has_inferred_function_name(true);
194 714954 : }
195 :
196 467956 : void FunctionLiteral::set_raw_inferred_name(
197 : const AstConsString* raw_inferred_name) {
198 : DCHECK_NOT_NULL(raw_inferred_name);
199 467956 : raw_inferred_name_ = raw_inferred_name;
200 : DCHECK(inferred_name_.is_null());
201 467956 : inferred_name_ = Handle<String>();
202 : scope()->set_has_inferred_function_name(true);
203 467956 : }
204 :
205 6591363 : bool FunctionLiteral::ShouldEagerCompile() const {
206 6591363 : return scope()->ShouldEagerCompile();
207 : }
208 :
209 726111 : void FunctionLiteral::SetShouldEagerCompile() {
210 726111 : scope()->set_should_eager_compile();
211 726112 : }
212 :
213 3636820 : bool FunctionLiteral::AllowsLazyCompilation() {
214 3636820 : return scope()->AllowsLazyCompilation();
215 : }
216 :
217 3618641 : bool FunctionLiteral::SafeToSkipArgumentsAdaptor() const {
218 : // TODO(bmeurer,verwaest): The --fast_calls_with_arguments_mismatches
219 : // is mostly here for checking the real-world impact of the calling
220 : // convention. There's not really a point in turning off this flag
221 : // otherwise, so we should remove it at some point, when we're done
222 : // with the experiments (https://crbug.com/v8/8895).
223 3618650 : return FLAG_fast_calls_with_arguments_mismatches &&
224 683602 : language_mode() == LanguageMode::kStrict &&
225 4235591 : scope()->arguments() == nullptr &&
226 3618641 : scope()->rest_parameter() == nullptr;
227 : }
228 :
229 0 : Handle<String> FunctionLiteral::name(Isolate* isolate) const {
230 0 : return raw_name_ ? raw_name_->string() : isolate->factory()->empty_string();
231 : }
232 :
233 10941116 : int FunctionLiteral::start_position() const {
234 10941116 : return scope()->start_position();
235 : }
236 :
237 :
238 5175057 : int FunctionLiteral::end_position() const {
239 5175057 : return scope()->end_position();
240 : }
241 :
242 :
243 4981764 : LanguageMode FunctionLiteral::language_mode() const {
244 4981764 : return scope()->language_mode();
245 : }
246 :
247 10153419 : FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
248 :
249 298208 : bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
250 596416 : if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
251 : DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
252 310392 : return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
253 : }
254 :
255 23 : std::unique_ptr<char[]> FunctionLiteral::GetDebugName() const {
256 : const AstConsString* cons_string;
257 23 : if (raw_name_ != nullptr && !raw_name_->IsEmpty()) {
258 : cons_string = raw_name_;
259 6 : } else if (raw_inferred_name_ != nullptr && !raw_inferred_name_->IsEmpty()) {
260 : cons_string = raw_inferred_name_;
261 6 : } else if (!inferred_name_.is_null()) {
262 : AllowHandleDereference allow_deref;
263 6 : return inferred_name_->ToCString();
264 : } else {
265 0 : char* empty_str = new char[1];
266 0 : empty_str[0] = 0;
267 : return std::unique_ptr<char[]>(empty_str);
268 : }
269 :
270 : // TODO(rmcilroy): Deal with two-character strings.
271 : std::vector<char> result_vec;
272 17 : std::forward_list<const AstRawString*> strings = cons_string->ToRawStrings();
273 34 : for (const AstRawString* string : strings) {
274 17 : if (!string->is_one_byte()) break;
275 335 : for (int i = 0; i < string->length(); i++) {
276 318 : result_vec.push_back(string->raw_data()[i]);
277 : }
278 : }
279 17 : std::unique_ptr<char[]> result(new char[result_vec.size() + 1]);
280 : memcpy(result.get(), result_vec.data(), result_vec.size());
281 17 : result[result_vec.size()] = '\0';
282 : return result;
283 : }
284 :
285 137835 : ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
286 : Kind kind, bool is_computed_name)
287 : : LiteralProperty(key, value, is_computed_name),
288 : kind_(kind),
289 137835 : emit_store_(true) {}
290 :
291 2914917 : ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
292 : Expression* key, Expression* value,
293 : bool is_computed_name)
294 2914917 : : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
295 7270254 : if (!is_computed_name && key->AsLiteral()->IsString() &&
296 : key->AsLiteral()->AsRawString() == ast_value_factory->proto_string()) {
297 6609 : kind_ = PROTOTYPE;
298 2908308 : } else if (value_->AsMaterializedLiteral() != nullptr) {
299 59957 : kind_ = MATERIALIZED_LITERAL;
300 2848351 : } else if (value_->IsLiteral()) {
301 1862621 : kind_ = CONSTANT;
302 : } else {
303 985730 : kind_ = COMPUTED;
304 : }
305 2914917 : }
306 :
307 3429575 : bool LiteralProperty::NeedsSetFunctionName() const {
308 3459052 : return is_computed_name() && (value_->IsAnonymousFunctionDefinition() ||
309 22480 : value_->IsConciseMethodDefinition() ||
310 3429574 : value_->IsAccessorFunctionDefinition());
311 : }
312 :
313 459706 : ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
314 : Kind kind, bool is_static,
315 : bool is_computed_name,
316 : bool is_private)
317 : : LiteralProperty(key, value, is_computed_name),
318 : kind_(kind),
319 : is_static_(is_static),
320 : is_private_(is_private),
321 459706 : private_or_computed_name_var_(nullptr) {}
322 :
323 2021158 : bool ObjectLiteral::Property::IsCompileTimeValue() const {
324 2021158 : return kind_ == CONSTANT ||
325 44244 : (kind_ == MATERIALIZED_LITERAL && value_->IsCompileTimeValue());
326 : }
327 :
328 :
329 0 : void ObjectLiteral::Property::set_emit_store(bool emit_store) {
330 3370 : emit_store_ = emit_store;
331 0 : }
332 :
333 250785 : bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
334 :
335 593651 : void ObjectLiteral::CalculateEmitStore(Zone* zone) {
336 : const auto GETTER = ObjectLiteral::Property::GETTER;
337 : const auto SETTER = ObjectLiteral::Property::SETTER;
338 :
339 : ZoneAllocationPolicy allocator(zone);
340 :
341 : CustomMatcherZoneHashMap table(
342 : Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
343 3618027 : for (int i = properties()->length() - 1; i >= 0; i--) {
344 3024361 : ObjectLiteral::Property* property = properties()->at(i);
345 3024361 : if (property->is_computed_name()) continue;
346 3003335 : if (property->IsPrototype()) continue;
347 2996729 : Literal* literal = property->key()->AsLiteral();
348 : DCHECK(!literal->IsNullLiteral());
349 :
350 2996729 : uint32_t hash = literal->Hash();
351 5993466 : ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
352 2996736 : if (entry->value == nullptr) {
353 2992638 : entry->value = property;
354 : } else {
355 : // We already have a later definition of this property, so we don't need
356 : // to emit a store for the current one.
357 : //
358 : // There are two subtleties here.
359 : //
360 : // (1) Emitting a store might actually be incorrect. For example, in {get
361 : // foo() {}, foo: 42}, the getter store would override the data property
362 : // (which, being a non-computed compile-time valued property, is already
363 : // part of the initial literal object.
364 : //
365 : // (2) If the later definition is an accessor (say, a getter), and the
366 : // current definition is a complementary accessor (here, a setter), then
367 : // we still must emit a store for the current definition.
368 :
369 : auto later_kind =
370 : static_cast<ObjectLiteral::Property*>(entry->value)->kind();
371 : bool complementary_accessors =
372 4098 : (property->kind() == GETTER && later_kind == SETTER) ||
373 215 : (property->kind() == SETTER && later_kind == GETTER);
374 4098 : if (!complementary_accessors) {
375 : property->set_emit_store(false);
376 3370 : if (later_kind == GETTER || later_kind == SETTER) {
377 1067 : entry->value = property;
378 : }
379 : }
380 : }
381 : }
382 593666 : }
383 :
384 2160 : void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
385 : // We still check for __proto__:null after computed property names.
386 8568 : for (; i < properties()->length(); i++) {
387 6418 : if (properties()->at(i)->IsNullPrototype()) {
388 : set_has_null_protoype(true);
389 : break;
390 : }
391 : }
392 2160 : }
393 :
394 267441 : int ObjectLiteral::InitDepthAndFlags() {
395 285349 : if (is_initialized()) return depth();
396 : bool is_simple = true;
397 : bool has_seen_prototype = false;
398 : bool needs_initial_allocation_site = false;
399 : int depth_acc = 1;
400 : uint32_t nof_properties = 0;
401 : uint32_t elements = 0;
402 : uint32_t max_element_index = 0;
403 4355541 : for (int i = 0; i < properties()->length(); i++) {
404 2055172 : ObjectLiteral::Property* property = properties()->at(i);
405 2055172 : if (property->IsPrototype()) {
406 : has_seen_prototype = true;
407 : // __proto__:null has no side-effects and is set directly on the
408 : // boilerplate.
409 4113 : if (property->IsNullPrototype()) {
410 : set_has_null_protoype(true);
411 4113 : continue;
412 : }
413 : DCHECK(!has_null_prototype());
414 : is_simple = false;
415 : continue;
416 : }
417 2051059 : if (nof_properties == boilerplate_properties_) {
418 : DCHECK(property->is_computed_name());
419 : is_simple = false;
420 2193 : if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
421 2193 : break;
422 : }
423 : DCHECK(!property->is_computed_name());
424 :
425 : MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
426 2048866 : if (literal != nullptr) {
427 45792 : int subliteral_depth = literal->InitDepthAndFlags() + 1;
428 45792 : if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
429 45792 : needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
430 : }
431 :
432 2048866 : Literal* key = property->key()->AsLiteral();
433 : Expression* value = property->value();
434 :
435 2048866 : bool is_compile_time_value = value->IsCompileTimeValue();
436 2048881 : is_simple = is_simple && is_compile_time_value;
437 :
438 : // Keep track of the number of elements in the object literal and
439 : // the largest element index. If the largest element index is
440 : // much larger than the number of elements, creating an object
441 : // literal with fast elements will be a waste of space.
442 2048881 : uint32_t element_index = 0;
443 2048891 : if (key->AsArrayIndex(&element_index)) {
444 784610 : max_element_index = Max(element_index, max_element_index);
445 784610 : elements++;
446 : } else {
447 : DCHECK(key->IsPropertyName());
448 : }
449 :
450 2048891 : nof_properties++;
451 : }
452 :
453 : set_depth(depth_acc);
454 : set_is_simple(is_simple);
455 : set_needs_initial_allocation_site(needs_initial_allocation_site);
456 249558 : set_has_elements(elements > 0);
457 250095 : set_fast_elements((max_element_index <= 32) ||
458 537 : ((2 * elements) >= max_element_index));
459 249558 : return depth_acc;
460 : }
461 :
462 207874 : void ObjectLiteral::BuildBoilerplateDescription(Isolate* isolate) {
463 207874 : if (!boilerplate_description_.is_null()) return;
464 :
465 : int index_keys = 0;
466 : bool has_seen_proto = false;
467 4145201 : for (int i = 0; i < properties()->length(); i++) {
468 1969719 : ObjectLiteral::Property* property = properties()->at(i);
469 1969719 : if (property->IsPrototype()) {
470 : has_seen_proto = true;
471 : continue;
472 : }
473 1966425 : if (property->is_computed_name()) continue;
474 :
475 1965871 : Literal* key = property->key()->AsLiteral();
476 1965871 : if (!key->IsPropertyName()) index_keys++;
477 : }
478 :
479 : Handle<ObjectBoilerplateDescription> boilerplate_description =
480 : isolate->factory()->NewObjectBoilerplateDescription(
481 205763 : boilerplate_properties_, properties()->length(), index_keys,
482 411526 : has_seen_proto);
483 :
484 : int position = 0;
485 4143481 : for (int i = 0; i < properties()->length(); i++) {
486 1969286 : ObjectLiteral::Property* property = properties()->at(i);
487 1972576 : if (property->IsPrototype()) continue;
488 :
489 1965996 : if (static_cast<uint32_t>(position) == boilerplate_properties_) {
490 : DCHECK(property->is_computed_name());
491 429 : break;
492 : }
493 : DCHECK(!property->is_computed_name());
494 :
495 : MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
496 1965567 : if (m_literal != nullptr) {
497 44460 : m_literal->BuildConstants(isolate);
498 : }
499 :
500 : // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
501 : // value for COMPUTED properties, the real value is filled in at
502 : // runtime. The enumeration order is maintained.
503 1965567 : Literal* key_literal = property->key()->AsLiteral();
504 1965567 : uint32_t element_index = 0;
505 : Handle<Object> key =
506 : key_literal->AsArrayIndex(&element_index)
507 782870 : ? isolate->factory()->NewNumberFromUint(element_index)
508 2748437 : : Handle<Object>::cast(key_literal->AsRawPropertyName()->string());
509 :
510 1965567 : Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
511 :
512 : // Add name, value pair to the fixed array.
513 3931134 : boilerplate_description->set_key_value(position++, *key, *value);
514 : }
515 :
516 : boilerplate_description->set_flags(EncodeLiteralType());
517 :
518 205766 : boilerplate_description_ = boilerplate_description;
519 : }
520 :
521 203292 : bool ObjectLiteral::IsFastCloningSupported() const {
522 : // The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
523 : // literals don't support copy-on-write (COW) elements for now.
524 : // TODO(mvstanton): make object literals support COW elements.
525 590882 : return fast_elements() && is_shallow() &&
526 : properties_count() <=
527 203292 : ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
528 : }
529 :
530 415285 : int ArrayLiteral::InitDepthAndFlags() {
531 420153 : if (is_initialized()) return depth();
532 :
533 : int constants_length =
534 410417 : first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
535 :
536 : // Fill in the literals.
537 410417 : bool is_simple = first_spread_index_ < 0;
538 : int depth_acc = 1;
539 : int array_index = 0;
540 13155451 : for (; array_index < constants_length; array_index++) {
541 6372515 : Expression* element = values()->at(array_index);
542 : MaterializedLiteral* literal = element->AsMaterializedLiteral();
543 6372515 : if (literal != nullptr) {
544 31937 : int subliteral_depth = literal->InitDepthAndFlags() + 1;
545 31935 : if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
546 : }
547 :
548 6372513 : if (!element->IsCompileTimeValue()) {
549 : is_simple = false;
550 : }
551 : }
552 :
553 : set_depth(depth_acc);
554 : set_is_simple(is_simple);
555 : // Array literals always need an initial allocation site to properly track
556 : // elements transitions.
557 : set_needs_initial_allocation_site(true);
558 410419 : return depth_acc;
559 : }
560 :
561 180150 : void ArrayLiteral::BuildBoilerplateDescription(Isolate* isolate) {
562 180150 : if (!boilerplate_description_.is_null()) return;
563 :
564 : int constants_length =
565 180150 : first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
566 : ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
567 : Handle<FixedArray> fixed_array =
568 180150 : isolate->factory()->NewFixedArrayWithHoles(constants_length);
569 :
570 : // Fill in the literals.
571 : bool is_holey = false;
572 : int array_index = 0;
573 12699634 : for (; array_index < constants_length; array_index++) {
574 6259735 : Expression* element = values()->at(array_index);
575 : DCHECK(!element->IsSpread());
576 : MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
577 6259735 : if (m_literal != nullptr) {
578 29123 : m_literal->BuildConstants(isolate);
579 : }
580 :
581 : // New handle scope here, needs to be after BuildContants().
582 : HandleScope scope(isolate);
583 6259735 : Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
584 6259736 : if (boilerplate_value->IsTheHole(isolate)) {
585 : is_holey = true;
586 : continue;
587 : }
588 :
589 5190167 : if (boilerplate_value->IsUninitialized(isolate)) {
590 : boilerplate_value = handle(Smi::kZero, isolate);
591 : }
592 :
593 : kind = GetMoreGeneralElementsKind(kind,
594 10380335 : boilerplate_value->OptimalElementsKind());
595 5190167 : fixed_array->set(array_index, *boilerplate_value);
596 : }
597 :
598 180152 : if (is_holey) kind = GetHoleyElementsKind(kind);
599 :
600 : // Simple and shallow arrays can be lazily copied, we transform the
601 : // elements array to a copy-on-write array.
602 254320 : if (is_simple() && depth() == 1 && array_index > 0 &&
603 : IsSmiOrObjectElementsKind(kind)) {
604 53952 : fixed_array->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
605 : }
606 :
607 : Handle<FixedArrayBase> elements = fixed_array;
608 180153 : if (IsDoubleElementsKind(kind)) {
609 : ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
610 3348 : elements = isolate->factory()->NewFixedDoubleArray(constants_length);
611 : // We are copying from non-fast-double to fast-double.
612 : ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
613 3348 : accessor->CopyElements(isolate, fixed_array, from_kind, elements,
614 6696 : constants_length);
615 : }
616 :
617 : boilerplate_description_ =
618 180153 : isolate->factory()->NewArrayBoilerplateDescription(kind, elements);
619 : }
620 :
621 382100 : bool ArrayLiteral::IsFastCloningSupported() const {
622 757065 : return depth() <= 1 &&
623 : values_.length() <=
624 382100 : ConstructorBuiltins::kMaximumClonedShallowArrayElements;
625 : }
626 :
627 224934 : bool MaterializedLiteral::IsSimple() const {
628 313045 : if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
629 241599 : if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
630 : DCHECK(IsRegExpLiteral());
631 : return false;
632 : }
633 :
634 8225305 : Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
635 : Isolate* isolate) {
636 8225305 : if (expression->IsLiteral()) {
637 15446250 : return expression->AsLiteral()->BuildValue(isolate);
638 : }
639 502180 : if (expression->IsCompileTimeValue()) {
640 41390 : if (expression->IsObjectLiteral()) {
641 17048 : ObjectLiteral* object_literal = expression->AsObjectLiteral();
642 : DCHECK(object_literal->is_simple());
643 17048 : return object_literal->boilerplate_description();
644 : } else {
645 : DCHECK(expression->IsArrayLiteral());
646 24342 : ArrayLiteral* array_literal = expression->AsArrayLiteral();
647 : DCHECK(array_literal->is_simple());
648 24342 : return array_literal->boilerplate_description();
649 : }
650 : }
651 460791 : return isolate->factory()->uninitialized_value();
652 : }
653 :
654 77727 : int MaterializedLiteral::InitDepthAndFlags() {
655 108843 : if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
656 82529 : if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
657 : DCHECK(IsRegExpLiteral());
658 : return 1;
659 : }
660 :
661 45792 : bool MaterializedLiteral::NeedsInitialAllocationSite() {
662 45792 : if (IsArrayLiteral()) {
663 35118 : return AsArrayLiteral()->needs_initial_allocation_site();
664 : }
665 28233 : if (IsObjectLiteral()) {
666 35676 : return AsObjectLiteral()->needs_initial_allocation_site();
667 : }
668 : DCHECK(IsRegExpLiteral());
669 : return false;
670 : }
671 :
672 73583 : void MaterializedLiteral::BuildConstants(Isolate* isolate) {
673 73583 : if (IsArrayLiteral()) {
674 57442 : AsArrayLiteral()->BuildBoilerplateDescription(isolate);
675 28721 : return;
676 : }
677 44862 : if (IsObjectLiteral()) {
678 68402 : AsObjectLiteral()->BuildBoilerplateDescription(isolate);
679 34202 : return;
680 : }
681 : DCHECK(IsRegExpLiteral());
682 : }
683 :
684 1731 : Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
685 : Isolate* isolate) {
686 : Handle<FixedArray> raw_strings = isolate->factory()->NewFixedArray(
687 1731 : this->raw_strings()->length(), AllocationType::kOld);
688 : bool raw_and_cooked_match = true;
689 7479 : for (int i = 0; i < raw_strings->length(); ++i) {
690 4712 : if (this->cooked_strings()->at(i) == nullptr ||
691 1838 : *this->raw_strings()->at(i)->string() !=
692 : *this->cooked_strings()->at(i)->string()) {
693 : raw_and_cooked_match = false;
694 : }
695 5748 : raw_strings->set(i, *this->raw_strings()->at(i)->string());
696 : }
697 : Handle<FixedArray> cooked_strings = raw_strings;
698 1731 : if (!raw_and_cooked_match) {
699 : cooked_strings = isolate->factory()->NewFixedArray(
700 1176 : this->cooked_strings()->length(), AllocationType::kOld);
701 5232 : for (int i = 0; i < cooked_strings->length(); ++i) {
702 2028 : if (this->cooked_strings()->at(i) != nullptr) {
703 992 : cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
704 : } else {
705 1036 : cooked_strings->set(i, ReadOnlyRoots(isolate).undefined_value());
706 : }
707 : }
708 : }
709 : return isolate->factory()->NewTemplateObjectDescription(raw_strings,
710 1731 : cooked_strings);
711 : }
712 :
713 : static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
714 : // Add is not commutative due to potential for string addition.
715 274875 : return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
716 : op == Token::BIT_XOR;
717 : }
718 :
719 : // Check for the pattern: x + 1.
720 : static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
721 : Expression** expr, Smi* literal) {
722 441254 : if (right->IsSmiLiteral()) {
723 127549 : *expr = left;
724 255098 : *literal = right->AsLiteral()->AsSmiLiteral();
725 : return true;
726 : }
727 : return false;
728 : }
729 :
730 374772 : bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
731 : Smi* literal) {
732 1024419 : return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
733 66482 : (IsCommutativeOperationWithSmiLiteral(op()) &&
734 441254 : MatchSmiLiteralOperation(right_, left_, subexpr, literal));
735 : }
736 :
737 : static bool IsTypeof(Expression* expr) {
738 1687380 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
739 1835481 : return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
740 : }
741 :
742 : // Check for the pattern: typeof <expression> equals <string literal>.
743 1687380 : static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
744 : Expression* right, Expression** expr,
745 : Literal** literal) {
746 1931536 : if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
747 100065 : *expr = left->AsUnaryOperation()->expression();
748 200130 : *literal = right->AsLiteral();
749 100065 : return true;
750 : }
751 : return false;
752 : }
753 :
754 893694 : bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
755 : Literal** literal) {
756 2581090 : return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
757 2481100 : MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
758 : }
759 :
760 :
761 : static bool IsVoidOfLiteral(Expression* expr) {
762 1586285 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
763 1636059 : return maybe_unary != nullptr && maybe_unary->op() == Token::VOID &&
764 : maybe_unary->expression()->IsLiteral();
765 : }
766 :
767 :
768 : // Check for the pattern: void <literal> equals <expression> or
769 : // undefined equals <expression>
770 1586285 : static bool MatchLiteralCompareUndefined(Expression* left,
771 : Token::Value op,
772 : Expression* right,
773 : Expression** expr) {
774 1588212 : if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
775 1129 : *expr = right;
776 1129 : return true;
777 : }
778 1645323 : if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
779 60120 : *expr = right;
780 60120 : return true;
781 : }
782 : return false;
783 : }
784 :
785 793632 : bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
786 2379919 : return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
787 2378944 : MatchLiteralCompareUndefined(right_, op(), left_, expr);
788 : }
789 :
790 : // Check for the pattern: null equals <expression>
791 : static bool MatchLiteralCompareNull(Expression* left,
792 : Token::Value op,
793 : Expression* right,
794 : Expression** expr) {
795 1470113 : if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
796 5223 : *expr = right;
797 : return true;
798 : }
799 : return false;
800 : }
801 :
802 732383 : bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
803 2928829 : return MatchLiteralCompareNull(left_, op(), right_, expr) ||
804 2195743 : MatchLiteralCompareNull(right_, op(), left_, expr);
805 : }
806 :
807 5178642 : Call::CallType Call::GetCallType() const {
808 5178642 : VariableProxy* proxy = expression()->AsVariableProxy();
809 5178642 : if (proxy != nullptr) {
810 4239670 : if (proxy->var()->IsUnallocated()) {
811 : return GLOBAL_CALL;
812 430756 : } else if (proxy->var()->IsLookupSlot()) {
813 : // Calls going through 'with' always use VariableMode::kDynamic rather
814 : // than VariableMode::kDynamicLocal or VariableMode::kDynamicGlobal.
815 : return proxy->var()->mode() == VariableMode::kDynamic ? WITH_CALL
816 178126 : : OTHER_CALL;
817 : }
818 : }
819 :
820 1191602 : if (expression()->IsSuperCallReference()) return SUPER_CALL;
821 :
822 : Property* property = expression()->AsProperty();
823 1187478 : if (property != nullptr) {
824 : bool is_super = property->IsSuperAccess();
825 826001 : if (property->key()->IsPropertyName()) {
826 821355 : return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
827 : } else {
828 4645 : return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
829 : }
830 : }
831 :
832 361477 : if (expression()->IsResolvedProperty()) {
833 : return RESOLVED_PROPERTY_CALL;
834 : }
835 :
836 361476 : return OTHER_CALL;
837 : }
838 :
839 92045 : CaseClause::CaseClause(Zone* zone, Expression* label,
840 : const ScopedPtrList<Statement>& statements)
841 92045 : : label_(label), statements_(0, nullptr) {
842 92045 : statements.CopyTo(&statements_, zone);
843 92045 : }
844 :
845 282631 : bool Literal::IsPropertyName() const {
846 9771558 : if (type() != kString) return false;
847 : uint32_t index;
848 8797079 : return !string_->AsArrayIndex(&index);
849 : }
850 :
851 4296447 : bool Literal::ToUint32(uint32_t* value) const {
852 4296447 : switch (type()) {
853 : case kString:
854 2729618 : return string_->AsArrayIndex(value);
855 : case kSmi:
856 1566773 : if (smi_ < 0) return false;
857 1566774 : *value = static_cast<uint32_t>(smi_);
858 1566774 : return true;
859 : case kHeapNumber:
860 130 : return DoubleToUint32IfEqualToSelf(AsNumber(), value);
861 : default:
862 : return false;
863 : }
864 : }
865 :
866 282019 : bool Literal::AsArrayIndex(uint32_t* value) const {
867 4296467 : return ToUint32(value) && *value != kMaxUInt32;
868 : }
869 :
870 7801467 : Handle<Object> Literal::BuildValue(Isolate* isolate) const {
871 7801467 : switch (type()) {
872 : case kSmi:
873 11508408 : return handle(Smi::FromInt(smi_), isolate);
874 : case kHeapNumber:
875 408160 : return isolate->factory()->NewNumber(number_, AllocationType::kOld);
876 : case kString:
877 1048648 : return string_->string();
878 : case kSymbol:
879 0 : return isolate->factory()->home_object_symbol();
880 : case kBoolean:
881 40065 : return isolate->factory()->ToBoolean(boolean_);
882 : case kNull:
883 2387 : return isolate->factory()->null_value();
884 : case kUndefined:
885 261 : return isolate->factory()->undefined_value();
886 : case kTheHole:
887 1069578 : return isolate->factory()->the_hole_value();
888 : case kBigInt:
889 : // This should never fail: the parser will never create a BigInt
890 : // literal that cannot be allocated.
891 4976 : return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
892 : }
893 0 : UNREACHABLE();
894 : }
895 :
896 381678 : bool Literal::ToBooleanIsTrue() const {
897 381678 : switch (type()) {
898 : case kSmi:
899 48519 : return smi_ != 0;
900 : case kHeapNumber:
901 172 : return DoubleToBoolean(number_);
902 : case kString:
903 878 : return !string_->IsEmpty();
904 : case kNull:
905 : case kUndefined:
906 : return false;
907 : case kBoolean:
908 332484 : return boolean_;
909 : case kBigInt: {
910 : const char* bigint_str = bigint_.c_str();
911 14 : size_t length = strlen(bigint_str);
912 : DCHECK_GT(length, 0);
913 14 : if (length == 1 && bigint_str[0] == '0') return false;
914 : // Skip over any radix prefix; BigInts with length > 1 only
915 : // begin with zero if they include a radix.
916 47 : for (size_t i = (bigint_str[0] == '0') ? 2 : 0; i < length; ++i) {
917 41 : if (bigint_str[i] != '0') return true;
918 : }
919 : return false;
920 : }
921 : case kSymbol:
922 0 : return true;
923 : case kTheHole:
924 0 : UNREACHABLE();
925 : }
926 0 : UNREACHABLE();
927 : }
928 :
929 3002500 : uint32_t Literal::Hash() {
930 : return IsString() ? AsRawString()->Hash()
931 7452528 : : ComputeLongHash(double_to_uint64(AsNumber()));
932 : }
933 :
934 :
935 : // static
936 77831 : bool Literal::Match(void* a, void* b) {
937 : Literal* x = static_cast<Literal*>(a);
938 : Literal* y = static_cast<Literal*>(b);
939 76549 : return (x->IsString() && y->IsString() &&
940 79113 : x->AsRawString() == y->AsRawString()) ||
941 1282 : (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
942 : }
943 :
944 3745559 : Literal* AstNodeFactory::NewNumberLiteral(double number, int pos) {
945 : int int_value;
946 3745559 : if (DoubleToSmiInteger(number, &int_value)) {
947 2953701 : return NewSmiLiteral(int_value, pos);
948 : }
949 1583716 : return new (zone_) Literal(number, pos);
950 : }
951 :
952 0 : const char* CallRuntime::debug_name() {
953 : #ifdef DEBUG
954 : return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
955 : : function_->name;
956 : #else
957 0 : return is_jsruntime() ? "(context function)" : function_->name;
958 : #endif // DEBUG
959 : }
960 :
961 : #define RETURN_LABELS(NodeType) \
962 : case k##NodeType: \
963 : return static_cast<const NodeType*>(this)->labels();
964 :
965 24387 : ZonePtrList<const AstRawString>* BreakableStatement::labels() const {
966 24387 : switch (node_type()) {
967 20850 : BREAKABLE_NODE_LIST(RETURN_LABELS)
968 255 : ITERATION_NODE_LIST(RETURN_LABELS)
969 : default:
970 0 : UNREACHABLE();
971 : }
972 : }
973 :
974 : #undef RETURN_LABELS
975 :
976 : } // namespace internal
977 121996 : } // namespace v8
|