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 34313 : IterationStatement* AstNode::AsIterationStatement() {
67 34313 : switch (node_type()) {
68 345 : ITERATION_NODE_LIST(RETURN_NODE);
69 : default:
70 : return nullptr;
71 : }
72 : }
73 :
74 0 : MaterializedLiteral* AstNode::AsMaterializedLiteral() {
75 20837363 : switch (node_type()) {
76 63973 : LITERAL_NODE_LIST(RETURN_NODE);
77 : default:
78 : return nullptr;
79 : }
80 : }
81 :
82 : #undef RETURN_NODE
83 :
84 425494 : bool Expression::IsSmiLiteral() const {
85 1238451 : return IsLiteral() && AsLiteral()->type() == Literal::kSmi;
86 : }
87 :
88 2807954 : bool Expression::IsNumberLiteral() const {
89 4627331 : return IsLiteral() && AsLiteral()->IsNumber();
90 : }
91 :
92 254110 : bool Expression::IsStringLiteral() const {
93 743373 : return IsLiteral() && AsLiteral()->type() == Literal::kString;
94 : }
95 :
96 9371543 : bool Expression::IsPropertyName() const {
97 16869705 : return IsLiteral() && AsLiteral()->IsPropertyName();
98 : }
99 :
100 8935 : bool Expression::IsNullLiteral() const {
101 1868281 : return IsLiteral() && AsLiteral()->type() == Literal::kNull;
102 : }
103 :
104 5122 : bool Expression::IsTheHoleLiteral() const {
105 5905 : return IsLiteral() && AsLiteral()->type() == Literal::kTheHole;
106 : }
107 :
108 15224019 : bool Expression::IsCompileTimeValue() {
109 15224019 : if (IsLiteral()) return true;
110 : MaterializedLiteral* literal = AsMaterializedLiteral();
111 1350875 : if (literal == nullptr) return false;
112 223765 : return literal->IsSimple();
113 : }
114 :
115 1581926 : bool Expression::IsUndefinedLiteral() const {
116 1984886 : if (IsLiteral() && AsLiteral()->type() == Literal::kUndefined) return true;
117 :
118 1572694 : const VariableProxy* var_proxy = AsVariableProxy();
119 1572694 : 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 1593785 : return var != nullptr && var->IsUnallocated() &&
124 207296 : var_proxy->raw_name()->IsOneByteEqualTo("undefined");
125 : }
126 :
127 961841 : bool Expression::ToBooleanIsTrue() const {
128 984650 : return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
129 : }
130 :
131 946862 : bool Expression::ToBooleanIsFalse() const {
132 979051 : return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
133 : }
134 :
135 0 : bool Expression::IsValidReferenceExpression() const {
136 0 : return IsProperty() ||
137 0 : (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
138 : }
139 :
140 11928169 : bool Expression::IsAnonymousFunctionDefinition() const {
141 1635645 : return (IsFunctionLiteral() &&
142 23508139 : AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
143 3712 : (IsClassLiteral() &&
144 11931881 : AsClassLiteral()->IsAnonymousFunctionDefinition());
145 : }
146 :
147 11548149 : bool Expression::IsConciseMethodDefinition() const {
148 12864931 : return IsFunctionLiteral() && IsConciseMethod(AsFunctionLiteral()->kind());
149 : }
150 :
151 11182525 : bool Expression::IsAccessorFunctionDefinition() const {
152 12119829 : return IsFunctionLiteral() && IsAccessorFunction(AsFunctionLiteral()->kind());
153 : }
154 :
155 2900124 : VariableProxy::VariableProxy(Variable* var, int start_position)
156 : : Expression(start_position, kVariableProxy),
157 : raw_name_(var->raw_name()),
158 2900124 : next_unresolved_(nullptr) {
159 : DCHECK(!var->is_this());
160 : bit_field_ |= IsAssignedField::encode(false) |
161 : IsResolvedField::encode(false) |
162 2900124 : HoleCheckModeField::encode(HoleCheckMode::kElided);
163 : BindTo(var);
164 2900124 : }
165 :
166 6582892 : VariableProxy::VariableProxy(const VariableProxy* copy_from)
167 : : Expression(copy_from->position(), kVariableProxy),
168 6582892 : next_unresolved_(nullptr) {
169 6582892 : bit_field_ = copy_from->bit_field_;
170 : DCHECK(!copy_from->is_resolved());
171 6582892 : raw_name_ = copy_from->raw_name_;
172 6582892 : }
173 :
174 39613738 : 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 42513862 : if (is_assigned()) var->set_maybe_assigned();
180 39613738 : }
181 :
182 14302098 : Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
183 : Expression* value, int pos)
184 14302098 : : Expression(pos, node_type), target_(target), value_(value) {
185 14302098 : bit_field_ |= TokenField::encode(op);
186 14302098 : }
187 :
188 711584 : void FunctionLiteral::set_inferred_name(Handle<String> inferred_name) {
189 : DCHECK(!inferred_name.is_null());
190 711584 : inferred_name_ = inferred_name;
191 : DCHECK(raw_inferred_name_ == nullptr || raw_inferred_name_->IsEmpty());
192 711584 : raw_inferred_name_ = nullptr;
193 : scope()->set_has_inferred_function_name(true);
194 711584 : }
195 :
196 465279 : void FunctionLiteral::set_raw_inferred_name(
197 : const AstConsString* raw_inferred_name) {
198 : DCHECK_NOT_NULL(raw_inferred_name);
199 465279 : raw_inferred_name_ = raw_inferred_name;
200 : DCHECK(inferred_name_.is_null());
201 465279 : inferred_name_ = Handle<String>();
202 : scope()->set_has_inferred_function_name(true);
203 465279 : }
204 :
205 6529397 : bool FunctionLiteral::ShouldEagerCompile() const {
206 6529397 : return scope()->ShouldEagerCompile();
207 : }
208 :
209 717407 : void FunctionLiteral::SetShouldEagerCompile() {
210 717407 : scope()->set_should_eager_compile();
211 717414 : }
212 :
213 3602690 : bool FunctionLiteral::AllowsLazyCompilation() {
214 3602690 : return scope()->AllowsLazyCompilation();
215 : }
216 :
217 3583186 : 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 3583188 : return FLAG_fast_calls_with_arguments_mismatches &&
224 685140 : language_mode() == LanguageMode::kStrict &&
225 4201700 : scope()->arguments() == nullptr &&
226 3583186 : 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 10845838 : int FunctionLiteral::start_position() const {
234 10845838 : return scope()->start_position();
235 : }
236 :
237 :
238 5133499 : int FunctionLiteral::end_position() const {
239 5133499 : return scope()->end_position();
240 : }
241 :
242 :
243 4938503 : LanguageMode FunctionLiteral::language_mode() const {
244 4938503 : return scope()->language_mode();
245 : }
246 :
247 10060726 : FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
248 :
249 296919 : bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
250 593838 : if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
251 : DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
252 309274 : 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 137547 : ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
286 : Kind kind, bool is_computed_name)
287 : : LiteralProperty(key, value, is_computed_name),
288 : kind_(kind),
289 137547 : emit_store_(true) {}
290 :
291 2908673 : ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
292 : Expression* key, Expression* value,
293 : bool is_computed_name)
294 2908673 : : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
295 7251559 : if (!is_computed_name && key->AsLiteral()->IsString() &&
296 : key->AsLiteral()->AsRawString() == ast_value_factory->proto_string()) {
297 6597 : kind_ = PROTOTYPE;
298 2902076 : } else if (value_->AsMaterializedLiteral() != nullptr) {
299 59867 : kind_ = MATERIALIZED_LITERAL;
300 2842209 : } else if (value_->IsLiteral()) {
301 1857392 : kind_ = CONSTANT;
302 : } else {
303 984817 : kind_ = COMPUTED;
304 : }
305 2908673 : }
306 :
307 3418007 : bool LiteralProperty::NeedsSetFunctionName() const {
308 3447379 : return is_computed_name() && (value_->IsAnonymousFunctionDefinition() ||
309 22473 : value_->IsConciseMethodDefinition() ||
310 3418007 : value_->IsAccessorFunctionDefinition());
311 : }
312 :
313 454454 : 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 454454 : private_or_computed_name_var_(nullptr) {}
322 :
323 2015119 : bool ObjectLiteral::Property::IsCompileTimeValue() const {
324 2015119 : return kind_ == CONSTANT ||
325 44188 : (kind_ == MATERIALIZED_LITERAL && value_->IsCompileTimeValue());
326 : }
327 :
328 :
329 0 : void ObjectLiteral::Property::set_emit_store(bool emit_store) {
330 3363 : emit_store_ = emit_store;
331 0 : }
332 :
333 250049 : bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
334 :
335 591054 : 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 3608905 : for (int i = properties()->length() - 1; i >= 0; i--) {
344 3017846 : ObjectLiteral::Property* property = properties()->at(i);
345 3017846 : if (property->is_computed_name()) continue;
346 2996867 : if (property->IsPrototype()) continue;
347 2990271 : Literal* literal = property->key()->AsLiteral();
348 : DCHECK(!literal->IsNullLiteral());
349 :
350 2990271 : uint32_t hash = literal->Hash();
351 5980542 : ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
352 2990271 : if (entry->value == nullptr) {
353 2986181 : 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 4090 : (property->kind() == GETTER && later_kind == SETTER) ||
373 214 : (property->kind() == SETTER && later_kind == GETTER);
374 4090 : if (!complementary_accessors) {
375 : property->set_emit_store(false);
376 3363 : if (later_kind == GETTER || later_kind == SETTER) {
377 1066 : entry->value = property;
378 : }
379 : }
380 : }
381 : }
382 591059 : }
383 :
384 2121 : void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
385 : // We still check for __proto__:null after computed property names.
386 8421 : for (; i < properties()->length(); i++) {
387 6310 : if (properties()->at(i)->IsNullPrototype()) {
388 : set_has_null_protoype(true);
389 : break;
390 : }
391 : }
392 2121 : }
393 :
394 265413 : int ObjectLiteral::InitDepthAndFlags() {
395 283274 : 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 4341494 : for (int i = 0; i < properties()->length(); i++) {
404 2049103 : ObjectLiteral::Property* property = properties()->at(i);
405 2049103 : if (property->IsPrototype()) {
406 : has_seen_prototype = true;
407 : // __proto__:null has no side-effects and is set directly on the
408 : // boilerplate.
409 4101 : if (property->IsNullPrototype()) {
410 : set_has_null_protoype(true);
411 4101 : continue;
412 : }
413 : DCHECK(!has_null_prototype());
414 : is_simple = false;
415 : continue;
416 : }
417 2045002 : if (nof_properties == boilerplate_properties_) {
418 : DCHECK(property->is_computed_name());
419 : is_simple = false;
420 2154 : if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
421 2154 : break;
422 : }
423 : DCHECK(!property->is_computed_name());
424 :
425 : MaterializedLiteral* literal = property->value()->AsMaterializedLiteral();
426 2042848 : if (literal != nullptr) {
427 45729 : int subliteral_depth = literal->InitDepthAndFlags() + 1;
428 45729 : if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
429 45729 : needs_initial_allocation_site |= literal->NeedsInitialAllocationSite();
430 : }
431 :
432 2042849 : Literal* key = property->key()->AsLiteral();
433 : Expression* value = property->value();
434 :
435 2042849 : bool is_compile_time_value = value->IsCompileTimeValue();
436 2042861 : 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 2042861 : uint32_t element_index = 0;
443 2042870 : if (key->AsArrayIndex(&element_index)) {
444 784541 : max_element_index = Max(element_index, max_element_index);
445 784541 : elements++;
446 : } else {
447 : DCHECK(key->IsPropertyName());
448 : }
449 :
450 2042870 : 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 247574 : set_has_elements(elements > 0);
457 248111 : set_fast_elements((max_element_index <= 32) ||
458 537 : ((2 * elements) >= max_element_index));
459 247574 : return depth_acc;
460 : }
461 :
462 206433 : void ObjectLiteral::BuildBoilerplateDescription(Isolate* isolate) {
463 206433 : if (!boilerplate_description_.is_null()) return;
464 :
465 : int index_keys = 0;
466 : bool has_seen_proto = false;
467 4133480 : for (int i = 0; i < properties()->length(); i++) {
468 1964578 : ObjectLiteral::Property* property = properties()->at(i);
469 1964578 : if (property->IsPrototype()) {
470 : has_seen_proto = true;
471 : continue;
472 : }
473 1961288 : if (property->is_computed_name()) continue;
474 :
475 1960734 : Literal* key = property->key()->AsLiteral();
476 1960734 : if (!key->IsPropertyName()) index_keys++;
477 : }
478 :
479 : Handle<ObjectBoilerplateDescription> boilerplate_description =
480 : isolate->factory()->NewObjectBoilerplateDescription(
481 204324 : boilerplate_properties_, properties()->length(), index_keys,
482 408648 : has_seen_proto);
483 :
484 : int position = 0;
485 4131752 : for (int i = 0; i < properties()->length(); i++) {
486 1964143 : ObjectLiteral::Property* property = properties()->at(i);
487 1967428 : if (property->IsPrototype()) continue;
488 :
489 1960858 : 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 1960429 : if (m_literal != nullptr) {
497 44414 : 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 1960429 : Literal* key_literal = property->key()->AsLiteral();
504 1960429 : uint32_t element_index = 0;
505 : Handle<Object> key =
506 : key_literal->AsArrayIndex(&element_index)
507 782809 : ? isolate->factory()->NewNumberFromUint(element_index)
508 2743238 : : Handle<Object>::cast(key_literal->AsRawPropertyName()->string());
509 :
510 1960429 : Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
511 :
512 : // Add name, value pair to the fixed array.
513 3920858 : boilerplate_description->set_key_value(position++, *key, *value);
514 : }
515 :
516 : boilerplate_description->set_flags(EncodeLiteralType());
517 :
518 204324 : boilerplate_description_ = boilerplate_description;
519 : }
520 :
521 201813 : 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 586512 : return fast_elements() && is_shallow() &&
526 : properties_count() <=
527 201813 : ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
528 : }
529 :
530 410029 : int ArrayLiteral::InitDepthAndFlags() {
531 414793 : if (is_initialized()) return depth();
532 :
533 : int constants_length =
534 405265 : first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
535 :
536 : // Fill in the literals.
537 405265 : bool is_simple = first_spread_index_ < 0;
538 : int depth_acc = 1;
539 : int array_index = 0;
540 13095965 : for (; array_index < constants_length; array_index++) {
541 6345343 : Expression* element = values()->at(array_index);
542 : MaterializedLiteral* literal = element->AsMaterializedLiteral();
543 6345343 : if (literal != nullptr) {
544 31533 : int subliteral_depth = literal->InitDepthAndFlags() + 1;
545 31539 : if (subliteral_depth > depth_acc) depth_acc = subliteral_depth;
546 : }
547 :
548 6345349 : 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 405272 : return depth_acc;
559 : }
560 :
561 176578 : void ArrayLiteral::BuildBoilerplateDescription(Isolate* isolate) {
562 176578 : if (!boilerplate_description_.is_null()) return;
563 :
564 : int constants_length =
565 176578 : first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
566 : ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
567 : Handle<FixedArray> fixed_array =
568 176578 : isolate->factory()->NewFixedArrayWithHoles(constants_length);
569 :
570 : // Fill in the literals.
571 : bool is_holey = false;
572 : int array_index = 0;
573 12648162 : for (; array_index < constants_length; array_index++) {
574 6235792 : Expression* element = values()->at(array_index);
575 : DCHECK(!element->IsSpread());
576 : MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
577 6235792 : if (m_literal != nullptr) {
578 28816 : m_literal->BuildConstants(isolate);
579 : }
580 :
581 : // New handle scope here, needs to be after BuildContants().
582 : HandleScope scope(isolate);
583 6235792 : Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
584 6235792 : if (boilerplate_value->IsTheHole(isolate)) {
585 : is_holey = true;
586 : continue;
587 : }
588 :
589 5166241 : if (boilerplate_value->IsUninitialized(isolate)) {
590 : boilerplate_value = handle(Smi::kZero, isolate);
591 : }
592 :
593 : kind = GetMoreGeneralElementsKind(kind,
594 10332482 : boilerplate_value->OptimalElementsKind());
595 5166241 : fixed_array->set(array_index, *boilerplate_value);
596 : }
597 :
598 176578 : 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 250650 : if (is_simple() && depth() == 1 && array_index > 0 &&
603 : IsSmiOrObjectElementsKind(kind)) {
604 53153 : fixed_array->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
605 : }
606 :
607 : Handle<FixedArrayBase> elements = fixed_array;
608 176578 : if (IsDoubleElementsKind(kind)) {
609 : ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
610 4280 : 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 4280 : accessor->CopyElements(isolate, fixed_array, from_kind, elements,
614 8560 : constants_length);
615 : }
616 :
617 : boilerplate_description_ =
618 176578 : isolate->factory()->NewArrayBoilerplateDescription(kind, elements);
619 : }
620 :
621 377085 : bool ArrayLiteral::IsFastCloningSupported() const {
622 747239 : return depth() <= 1 &&
623 : values_.length() <=
624 377085 : ConstructorBuiltins::kMaximumClonedShallowArrayElements;
625 : }
626 :
627 223768 : bool MaterializedLiteral::IsSimple() const {
628 311466 : if (IsArrayLiteral()) return AsArrayLiteral()->is_simple();
629 240095 : if (IsObjectLiteral()) return AsObjectLiteral()->is_simple();
630 : DCHECK(IsRegExpLiteral());
631 : return false;
632 : }
633 :
634 8196220 : Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
635 : Isolate* isolate) {
636 8196220 : if (expression->IsLiteral()) {
637 15405252 : return expression->AsLiteral()->BuildValue(isolate);
638 : }
639 493594 : if (expression->IsCompileTimeValue()) {
640 41155 : if (expression->IsObjectLiteral()) {
641 16838 : ObjectLiteral* object_literal = expression->AsObjectLiteral();
642 : DCHECK(object_literal->is_simple());
643 16838 : return object_literal->boilerplate_description();
644 : } else {
645 : DCHECK(expression->IsArrayLiteral());
646 24317 : ArrayLiteral* array_literal = expression->AsArrayLiteral();
647 : DCHECK(array_literal->is_simple());
648 24317 : return array_literal->boilerplate_description();
649 : }
650 : }
651 452439 : return isolate->factory()->uninitialized_value();
652 : }
653 :
654 77262 : int MaterializedLiteral::InitDepthAndFlags() {
655 108171 : if (IsArrayLiteral()) return AsArrayLiteral()->InitDepthAndFlags();
656 82010 : if (IsObjectLiteral()) return AsObjectLiteral()->InitDepthAndFlags();
657 : DCHECK(IsRegExpLiteral());
658 : return 1;
659 : }
660 :
661 45729 : bool MaterializedLiteral::NeedsInitialAllocationSite() {
662 45729 : if (IsArrayLiteral()) {
663 35116 : return AsArrayLiteral()->needs_initial_allocation_site();
664 : }
665 28171 : if (IsObjectLiteral()) {
666 35554 : return AsObjectLiteral()->needs_initial_allocation_site();
667 : }
668 : DCHECK(IsRegExpLiteral());
669 : return false;
670 : }
671 :
672 73230 : void MaterializedLiteral::BuildConstants(Isolate* isolate) {
673 73230 : if (IsArrayLiteral()) {
674 57222 : AsArrayLiteral()->BuildBoilerplateDescription(isolate);
675 28611 : return;
676 : }
677 44619 : if (IsObjectLiteral()) {
678 67916 : AsObjectLiteral()->BuildBoilerplateDescription(isolate);
679 33958 : 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 272893 : 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 433372 : if (right->IsSmiLiteral()) {
723 120823 : *expr = left;
724 241646 : *literal = right->AsLiteral()->AsSmiLiteral();
725 : return true;
726 : }
727 : return false;
728 : }
729 :
730 368807 : bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
731 : Smi* literal) {
732 1010507 : return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
733 64565 : (IsCommutativeOperationWithSmiLiteral(op()) &&
734 433372 : MatchSmiLiteralOperation(right_, left_, subexpr, literal));
735 : }
736 :
737 : static bool IsTypeof(Expression* expr) {
738 1678751 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
739 1825961 : return maybe_unary != nullptr && maybe_unary->op() == Token::TYPEOF;
740 : }
741 :
742 : // Check for the pattern: typeof <expression> equals <string literal>.
743 1678751 : static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
744 : Expression* right, Expression** expr,
745 : Literal** literal) {
746 1921387 : if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
747 99435 : *expr = left->AsUnaryOperation()->expression();
748 198870 : *literal = right->AsLiteral();
749 99435 : return true;
750 : }
751 : return false;
752 : }
753 :
754 889063 : bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
755 : Literal** literal) {
756 2567818 : return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
757 2468448 : MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
758 : }
759 :
760 :
761 : static bool IsVoidOfLiteral(Expression* expr) {
762 1578277 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
763 1627791 : 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 1578277 : static bool MatchLiteralCompareUndefined(Expression* left,
771 : Token::Value op,
772 : Expression* right,
773 : Expression** expr) {
774 1580204 : if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
775 1129 : *expr = right;
776 1129 : return true;
777 : }
778 1637084 : if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
779 59888 : *expr = right;
780 59888 : return true;
781 : }
782 : return false;
783 : }
784 :
785 789627 : bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
786 2367904 : return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
787 2366929 : 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 1462536 : if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
796 5185 : *expr = right;
797 : return true;
798 : }
799 : return false;
800 : }
801 :
802 728613 : bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
803 2913750 : return MatchLiteralCompareNull(left_, op(), right_, expr) ||
804 2184435 : MatchLiteralCompareNull(right_, op(), left_, expr);
805 : }
806 :
807 5158517 : Call::CallType Call::GetCallType() const {
808 5158517 : VariableProxy* proxy = expression()->AsVariableProxy();
809 5158517 : if (proxy != nullptr) {
810 4232082 : if (proxy->var()->IsUnallocated()) {
811 : return GLOBAL_CALL;
812 422658 : } 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 177727 : : OTHER_CALL;
817 : }
818 : }
819 :
820 1171366 : if (expression()->IsSuperCallReference()) return SUPER_CALL;
821 :
822 : Property* property = expression()->AsProperty();
823 1167111 : if (property != nullptr) {
824 : bool is_super = property->IsSuperAccess();
825 815729 : if (property->key()->IsPropertyName()) {
826 811120 : return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
827 : } else {
828 4606 : return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
829 : }
830 : }
831 :
832 351382 : if (expression()->IsResolvedProperty()) {
833 : return RESOLVED_PROPERTY_CALL;
834 : }
835 :
836 351380 : return OTHER_CALL;
837 : }
838 :
839 91625 : CaseClause::CaseClause(Zone* zone, Expression* label,
840 : const ScopedPtrList<Statement>& statements)
841 91625 : : label_(label), statements_(0, nullptr) {
842 91625 : statements.CopyTo(&statements_, zone);
843 91625 : }
844 :
845 279378 : bool Literal::IsPropertyName() const {
846 9738281 : if (type() != kString) return false;
847 : uint32_t index;
848 8764477 : return !string_->AsArrayIndex(&index);
849 : }
850 :
851 4282027 : bool Literal::ToUint32(uint32_t* value) const {
852 4282027 : switch (type()) {
853 : case kString:
854 2715331 : return string_->AsArrayIndex(value);
855 : case kSmi:
856 1566644 : if (smi_ < 0) return false;
857 1566644 : *value = static_cast<uint32_t>(smi_);
858 1566644 : return true;
859 : case kHeapNumber:
860 130 : return DoubleToUint32IfEqualToSelf(AsNumber(), value);
861 : default:
862 : return false;
863 : }
864 : }
865 :
866 278771 : bool Literal::AsArrayIndex(uint32_t* value) const {
867 4282061 : return ToUint32(value) && *value != kMaxUInt32;
868 : }
869 :
870 7779699 : Handle<Object> Literal::BuildValue(Isolate* isolate) const {
871 7779699 : switch (type()) {
872 : case kSmi:
873 11466110 : return handle(Smi::FromInt(smi_), isolate);
874 : case kHeapNumber:
875 409984 : return isolate->factory()->NewNumber(number_, AllocationType::kOld);
876 : case kString:
877 1044080 : return string_->string();
878 : case kSymbol:
879 0 : return isolate->factory()->home_object_symbol();
880 : case kBoolean:
881 39938 : return isolate->factory()->ToBoolean(boolean_);
882 : case kNull:
883 2373 : return isolate->factory()->null_value();
884 : case kUndefined:
885 261 : return isolate->factory()->undefined_value();
886 : case kTheHole:
887 1069560 : 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 379689 : bool Literal::ToBooleanIsTrue() const {
897 379689 : switch (type()) {
898 : case kSmi:
899 48490 : 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 330526 : 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 2996027 : uint32_t Literal::Hash() {
930 : return IsString() ? AsRawString()->Hash()
931 7439512 : : ComputeLongHash(double_to_uint64(AsNumber()));
932 : }
933 :
934 :
935 : // static
936 77224 : bool Literal::Match(void* a, void* b) {
937 : Literal* x = static_cast<Literal*>(a);
938 : Literal* y = static_cast<Literal*>(b);
939 75941 : return (x->IsString() && y->IsString() &&
940 78560 : x->AsRawString() == y->AsRawString()) ||
941 1282 : (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
942 : }
943 :
944 3751774 : Literal* AstNodeFactory::NewNumberLiteral(double number, int pos) {
945 : int int_value;
946 3751774 : if (DoubleToSmiInteger(number, &int_value)) {
947 2899512 : return NewSmiLiteral(int_value, pos);
948 : }
949 1704521 : 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 24362 : ZonePtrList<const AstRawString>* BreakableStatement::labels() const {
966 24362 : switch (node_type()) {
967 20826 : 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 120216 : } // namespace v8
|