Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/ast/ast.h"
6 :
7 : #include <cmath> // For isfinite.
8 :
9 : #include "src/ast/compile-time-value.h"
10 : #include "src/ast/prettyprinter.h"
11 : #include "src/ast/scopes.h"
12 : #include "src/base/hashmap.h"
13 : #include "src/builtins/builtins-constructor.h"
14 : #include "src/builtins/builtins.h"
15 : #include "src/code-stubs.h"
16 : #include "src/contexts.h"
17 : #include "src/conversions.h"
18 : #include "src/double.h"
19 : #include "src/elements.h"
20 : #include "src/objects-inl.h"
21 : #include "src/objects/literal-objects.h"
22 : #include "src/property-details.h"
23 : #include "src/property.h"
24 : #include "src/string-stream.h"
25 : #include "src/type-info.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 294281 : IterationStatement* AstNode::AsIterationStatement() {
66 294281 : switch (node_type()) {
67 447 : ITERATION_NODE_LIST(RETURN_NODE);
68 : default:
69 : return nullptr;
70 : }
71 : }
72 :
73 83904 : BreakableStatement* AstNode::AsBreakableStatement() {
74 83904 : switch (node_type()) {
75 59948 : BREAKABLE_NODE_LIST(RETURN_NODE);
76 15840 : ITERATION_NODE_LIST(RETURN_NODE);
77 : default:
78 : return nullptr;
79 : }
80 : }
81 :
82 36326821 : MaterializedLiteral* AstNode::AsMaterializedLiteral() {
83 36326821 : switch (node_type()) {
84 40110 : LITERAL_NODE_LIST(RETURN_NODE);
85 : default:
86 : return nullptr;
87 : }
88 : }
89 :
90 : #undef RETURN_NODE
91 :
92 1107176 : bool Expression::IsSmiLiteral() const {
93 3292362 : return IsLiteral() && AsLiteral()->raw_value()->IsSmi();
94 : }
95 :
96 2523645 : bool Expression::IsNumberLiteral() const {
97 8523985 : return IsLiteral() && AsLiteral()->raw_value()->IsNumber();
98 : }
99 :
100 1820993 : bool Expression::IsStringLiteral() const {
101 5365567 : return IsLiteral() && AsLiteral()->raw_value()->IsString();
102 : }
103 :
104 28750032 : bool Expression::IsPropertyName() const {
105 102566629 : return IsLiteral() && AsLiteral()->IsPropertyName();
106 : }
107 :
108 3695693 : bool Expression::IsNullLiteral() const {
109 7391386 : if (!IsLiteral()) return false;
110 2313446 : return AsLiteral()->raw_value()->IsNull();
111 : }
112 :
113 4429841 : bool Expression::IsUndefinedLiteral() const {
114 5891558 : if (IsLiteral() && AsLiteral()->raw_value()->IsUndefined()) return true;
115 :
116 6018358 : const VariableProxy* var_proxy = AsVariableProxy();
117 4395251 : if (var_proxy == nullptr) return false;
118 : Variable* var = var_proxy->var();
119 : // The global identifier "undefined" is immutable. Everything
120 : // else could be reassigned.
121 3343400 : return var != NULL && var->IsUnallocated() &&
122 1720292 : var_proxy->raw_name()->IsOneByteEqualTo("undefined");
123 : }
124 :
125 2502865 : bool Expression::ToBooleanIsTrue() const {
126 5033739 : return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
127 : }
128 :
129 2504348 : bool Expression::ToBooleanIsFalse() const {
130 5044355 : return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
131 : }
132 :
133 11747171 : bool Expression::IsValidReferenceExpression() const {
134 : // We don't want expressions wrapped inside RewritableExpression to be
135 : // considered as valid reference expressions, as they will be rewritten
136 : // to something (most probably involving a do expression).
137 11747171 : if (IsRewritableExpression()) return false;
138 16861541 : return IsProperty() ||
139 10218820 : (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
140 : }
141 :
142 0 : bool Expression::IsValidReferenceExpressionOrThis() const {
143 0 : return IsValidReferenceExpression() ||
144 0 : (IsVariableProxy() && AsVariableProxy()->is_this());
145 : }
146 :
147 19136508 : bool Expression::IsAnonymousFunctionDefinition() const {
148 1534518 : return (IsFunctionLiteral() &&
149 37454591 : AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
150 3765 : (IsDoExpression() &&
151 19140272 : AsDoExpression()->IsAnonymousFunctionDefinition());
152 : }
153 :
154 11030 : void Expression::MarkTail() {
155 11030 : if (IsConditional()) {
156 280 : AsConditional()->MarkTail();
157 10890 : } else if (IsCall()) {
158 3667 : AsCall()->MarkTail();
159 7223 : } else if (IsBinaryOperation()) {
160 2484 : AsBinaryOperation()->MarkTail();
161 : }
162 11030 : }
163 :
164 0 : bool DoExpression::IsAnonymousFunctionDefinition() const {
165 : // This is specifically to allow DoExpressions to represent ClassLiterals.
166 7055 : return represented_function_ != nullptr &&
167 3290 : represented_function_->raw_name()->IsEmpty();
168 : }
169 :
170 53418581 : bool Statement::IsJump() const {
171 68999956 : switch (node_type()) {
172 : #define JUMP_NODE_LIST(V) \
173 : V(Block) \
174 : V(ExpressionStatement) \
175 : V(ContinueStatement) \
176 : V(BreakStatement) \
177 : V(ReturnStatement) \
178 : V(IfStatement)
179 : #define GENERATE_CASE(Node) \
180 : case k##Node: \
181 : return static_cast<const Node*>(this)->IsJump();
182 26433281 : JUMP_NODE_LIST(GENERATE_CASE)
183 : #undef GENERATE_CASE
184 : #undef JUMP_NODE_LIST
185 : default:
186 937730 : return false;
187 : }
188 : }
189 :
190 27512578 : VariableProxy::VariableProxy(Variable* var, int start_position)
191 : : Expression(start_position, kVariableProxy),
192 : raw_name_(var->raw_name()),
193 13756289 : next_unresolved_(nullptr) {
194 : bit_field_ |= IsThisField::encode(var->is_this()) |
195 : IsAssignedField::encode(false) |
196 : IsResolvedField::encode(false) |
197 13756289 : HoleCheckModeField::encode(HoleCheckMode::kElided);
198 : BindTo(var);
199 13756289 : }
200 :
201 124212310 : VariableProxy::VariableProxy(const AstRawString* name,
202 : VariableKind variable_kind, int start_position)
203 : : Expression(start_position, kVariableProxy),
204 : raw_name_(name),
205 124212310 : next_unresolved_(nullptr) {
206 124212310 : bit_field_ |= IsThisField::encode(variable_kind == THIS_VARIABLE) |
207 : IsAssignedField::encode(false) |
208 : IsResolvedField::encode(false) |
209 124212310 : HoleCheckModeField::encode(HoleCheckMode::kElided);
210 124212310 : }
211 :
212 2534705 : VariableProxy::VariableProxy(const VariableProxy* copy_from)
213 : : Expression(copy_from->position(), kVariableProxy),
214 5069410 : next_unresolved_(nullptr) {
215 2534705 : bit_field_ = copy_from->bit_field_;
216 : DCHECK(!copy_from->is_resolved());
217 2534705 : raw_name_ = copy_from->raw_name_;
218 2534705 : }
219 :
220 93254615 : void VariableProxy::BindTo(Variable* var) {
221 : DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name());
222 : set_var(var);
223 : set_is_resolved();
224 : var->set_is_used();
225 107010904 : if (is_assigned()) var->set_maybe_assigned();
226 93254615 : }
227 :
228 28627431 : void VariableProxy::AssignFeedbackSlots(FeedbackVectorSpec* spec,
229 : TypeofMode typeof_mode,
230 3032345 : FeedbackSlotCache* cache) {
231 28627431 : if (UsesVariableFeedbackSlot()) {
232 : // VariableProxies that point to the same Variable within a function can
233 : // make their loads from the same IC slot.
234 5978997 : if (var()->IsUnallocated() || var()->mode() == DYNAMIC_GLOBAL) {
235 4772404 : FeedbackSlot slot = cache->Get(typeof_mode, var());
236 4772402 : if (!slot.IsInvalid()) {
237 1740057 : variable_feedback_slot_ = slot;
238 30367487 : return;
239 : }
240 3032345 : variable_feedback_slot_ = spec->AddLoadGlobalICSlot(typeof_mode);
241 : cache->Put(typeof_mode, var(), variable_feedback_slot_);
242 : } else {
243 324414 : variable_feedback_slot_ = spec->AddLoadICSlot();
244 : }
245 : }
246 : }
247 :
248 10911912 : static void AssignVectorSlots(Expression* expr, FeedbackVectorSpec* spec,
249 : LanguageMode language_mode,
250 : FeedbackSlot* out_slot) {
251 10911912 : Property* property = expr->AsProperty();
252 10911922 : LhsKind assign_type = Property::GetAssignType(property);
253 : // TODO(ishell): consider using ICSlotCache for variables here.
254 19060790 : if (assign_type == VARIABLE &&
255 8148865 : expr->AsVariableProxy()->var()->IsUnallocated()) {
256 998372 : *out_slot = spec->AddStoreGlobalICSlot(language_mode);
257 :
258 9913560 : } else if (assign_type == NAMED_PROPERTY) {
259 2551741 : *out_slot = spec->AddStoreICSlot(language_mode);
260 :
261 7361819 : } else if (assign_type == KEYED_PROPERTY) {
262 210490 : *out_slot = spec->AddKeyedStoreICSlot(language_mode);
263 : }
264 10911932 : }
265 :
266 11513 : void ForInStatement::AssignFeedbackSlots(FeedbackVectorSpec* spec,
267 : LanguageMode language_mode,
268 11513 : FeedbackSlotCache* cache) {
269 23026 : AssignVectorSlots(each(), spec, language_mode, &each_slot_);
270 11513 : for_in_feedback_slot_ = spec->AddGeneralSlot();
271 11513 : }
272 :
273 28097097 : Assignment::Assignment(Token::Value op, Expression* target, Expression* value,
274 : int pos)
275 : : Expression(pos, kAssignment),
276 : target_(target),
277 : value_(value),
278 28097097 : binary_operation_(NULL) {
279 : bit_field_ |= IsUninitializedField::encode(false) |
280 : KeyTypeField::encode(ELEMENT) |
281 28097097 : StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op);
282 28097097 : }
283 :
284 10624862 : void Assignment::AssignFeedbackSlots(FeedbackVectorSpec* spec,
285 : LanguageMode language_mode,
286 10624862 : FeedbackSlotCache* cache) {
287 21249724 : AssignVectorSlots(target(), spec, language_mode, &slot_);
288 10624871 : }
289 :
290 275545 : void CountOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
291 : LanguageMode language_mode,
292 275545 : FeedbackSlotCache* cache) {
293 551090 : AssignVectorSlots(expression(), spec, language_mode, &slot_);
294 : // Assign a slot to collect feedback about binary operations. Used only in
295 : // ignition. Fullcodegen uses AstId to record type feedback.
296 275545 : binary_operation_slot_ = spec->AddInterpreterBinaryOpICSlot();
297 275545 : }
298 :
299 :
300 710940 : Token::Value Assignment::binary_op() const {
301 710940 : switch (op()) {
302 : case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
303 8472 : case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
304 7568 : case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
305 6535 : case Token::ASSIGN_SHL: return Token::SHL;
306 7854 : case Token::ASSIGN_SAR: return Token::SAR;
307 7117 : case Token::ASSIGN_SHR: return Token::SHR;
308 631286 : case Token::ASSIGN_ADD: return Token::ADD;
309 11451 : case Token::ASSIGN_SUB: return Token::SUB;
310 7954 : case Token::ASSIGN_MUL: return Token::MUL;
311 7080 : case Token::ASSIGN_DIV: return Token::DIV;
312 8082 : case Token::ASSIGN_MOD: return Token::MOD;
313 0 : default: UNREACHABLE();
314 : }
315 : return Token::ILLEGAL;
316 : }
317 :
318 5458779 : bool FunctionLiteral::ShouldEagerCompile() const {
319 5458779 : return scope()->ShouldEagerCompile();
320 : }
321 :
322 1096879 : void FunctionLiteral::SetShouldEagerCompile() {
323 1096879 : scope()->set_should_eager_compile();
324 1096884 : }
325 :
326 6235391 : bool FunctionLiteral::AllowsLazyCompilation() {
327 6235391 : return scope()->AllowsLazyCompilation();
328 : }
329 :
330 :
331 12922248 : int FunctionLiteral::start_position() const {
332 12922248 : return scope()->start_position();
333 : }
334 :
335 :
336 9749704 : int FunctionLiteral::end_position() const {
337 9749704 : return scope()->end_position();
338 : }
339 :
340 :
341 11610958 : LanguageMode FunctionLiteral::language_mode() const {
342 11610958 : return scope()->language_mode();
343 : }
344 :
345 28041180 : FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
346 :
347 2452017 : bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
348 4904034 : if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
349 : DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
350 3716580 : return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
351 : }
352 :
353 220800 : ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
354 : Kind kind, bool is_computed_name)
355 : : LiteralProperty(key, value, is_computed_name),
356 : kind_(kind),
357 441600 : emit_store_(true) {}
358 :
359 9378466 : ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
360 : Expression* key, Expression* value,
361 : bool is_computed_name)
362 4697000 : : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
363 9378468 : if (!is_computed_name &&
364 : key->AsLiteral()->raw_value()->EqualsString(
365 9362934 : ast_value_factory->proto_string())) {
366 92665 : kind_ = PROTOTYPE;
367 9208674 : } else if (value_->AsMaterializedLiteral() != NULL) {
368 297937 : kind_ = MATERIALIZED_LITERAL;
369 4306400 : } else if (value_->IsLiteral()) {
370 2050908 : kind_ = CONSTANT;
371 : } else {
372 2255492 : kind_ = COMPUTED;
373 : }
374 4697002 : }
375 :
376 293714 : FeedbackSlot LiteralProperty::GetStoreDataPropertySlot() const {
377 293714 : int offset = FunctionLiteral::NeedsHomeObject(value_) ? 1 : 0;
378 293714 : return GetSlot(offset);
379 : }
380 :
381 0 : void LiteralProperty::SetStoreDataPropertySlot(FeedbackSlot slot) {
382 307523 : int offset = FunctionLiteral::NeedsHomeObject(value_) ? 1 : 0;
383 0 : return SetSlot(slot, offset);
384 : }
385 :
386 293714 : bool LiteralProperty::NeedsSetFunctionName() const {
387 299192 : return is_computed_name_ &&
388 10666 : (value_->IsAnonymousFunctionDefinition() ||
389 9458 : (value_->IsFunctionLiteral() &&
390 297984 : IsConciseMethod(value_->AsFunctionLiteral()->kind())));
391 : }
392 :
393 350663 : ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
394 : Kind kind, bool is_static,
395 : bool is_computed_name)
396 : : LiteralProperty(key, value, is_computed_name),
397 : kind_(kind),
398 350663 : is_static_(is_static) {}
399 :
400 43578 : void ClassLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
401 : LanguageMode language_mode,
402 390618 : FeedbackSlotCache* cache) {
403 : // This logic that computes the number of slots needed for vector store
404 : // ICs must mirror BytecodeGenerator::VisitClassLiteral.
405 43578 : if (FunctionLiteral::NeedsHomeObject(constructor())) {
406 1204 : home_object_slot_ = spec->AddStoreICSlot(language_mode);
407 : }
408 :
409 43578 : if (NeedsProxySlot()) {
410 0 : proxy_slot_ = spec->AddStoreICSlot(language_mode);
411 : }
412 :
413 650502 : for (int i = 0; i < properties()->length(); i++) {
414 303462 : ClassLiteral::Property* property = properties()->at(i);
415 303462 : Expression* value = property->value();
416 303462 : if (FunctionLiteral::NeedsHomeObject(value)) {
417 : property->SetSlot(spec->AddStoreICSlot(language_mode));
418 : }
419 : property->SetStoreDataPropertySlot(
420 : spec->AddStoreDataPropertyInLiteralICSlot());
421 : }
422 43578 : }
423 :
424 4354764 : bool ObjectLiteral::Property::IsCompileTimeValue() const {
425 4354764 : return kind_ == CONSTANT ||
426 363519 : (kind_ == MATERIALIZED_LITERAL &&
427 4718283 : CompileTimeValue::IsCompileTimeValue(value_));
428 : }
429 :
430 :
431 0 : void ObjectLiteral::Property::set_emit_store(bool emit_store) {
432 818 : emit_store_ = emit_store;
433 0 : }
434 :
435 1177670 : bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
436 :
437 752293 : void ObjectLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
438 : LanguageMode language_mode,
439 4078660 : FeedbackSlotCache* cache) {
440 : MaterializedLiteral::AssignFeedbackSlots(spec, language_mode, cache);
441 :
442 : // This logic that computes the number of slots needed for vector store
443 : // ics must mirror FullCodeGenerator::VisitObjectLiteral.
444 : int property_index = 0;
445 6644612 : for (; property_index < properties()->length(); property_index++) {
446 3193885 : ObjectLiteral::Property* property = properties()->at(property_index);
447 3815873 : if (property->is_computed_name()) break;
448 2570013 : if (property->IsCompileTimeValue()) continue;
449 :
450 621988 : Literal* key = property->key()->AsLiteral();
451 : Expression* value = property->value();
452 621988 : switch (property->kind()) {
453 : case ObjectLiteral::Property::SPREAD:
454 : case ObjectLiteral::Property::CONSTANT:
455 0 : UNREACHABLE();
456 : case ObjectLiteral::Property::MATERIALIZED_LITERAL:
457 : // Fall through.
458 : case ObjectLiteral::Property::COMPUTED:
459 : // It is safe to use [[Put]] here because the boilerplate already
460 : // contains computed properties with an uninitialized value.
461 575795 : if (key->IsStringLiteral()) {
462 575017 : if (property->emit_store()) {
463 : property->SetSlot(spec->AddStoreOwnICSlot());
464 574804 : if (FunctionLiteral::NeedsHomeObject(value)) {
465 : property->SetSlot(spec->AddStoreICSlot(language_mode), 1);
466 : }
467 : }
468 : break;
469 : }
470 778 : if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
471 : property->SetSlot(spec->AddStoreICSlot(language_mode));
472 : }
473 : break;
474 : case ObjectLiteral::Property::PROTOTYPE:
475 : break;
476 : case ObjectLiteral::Property::GETTER:
477 3660 : if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
478 : property->SetSlot(spec->AddStoreICSlot(language_mode));
479 : }
480 : break;
481 : case ObjectLiteral::Property::SETTER:
482 2532 : if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
483 : property->SetSlot(spec->AddStoreICSlot(language_mode));
484 : }
485 : break;
486 : }
487 : }
488 :
489 760415 : for (; property_index < properties()->length(); property_index++) {
490 8122 : ObjectLiteral::Property* property = properties()->at(property_index);
491 :
492 4061 : Expression* value = property->value();
493 4061 : if (property->kind() != ObjectLiteral::Property::PROTOTYPE) {
494 4011 : if (FunctionLiteral::NeedsHomeObject(value)) {
495 : property->SetSlot(spec->AddStoreICSlot(language_mode));
496 : }
497 : }
498 : property->SetStoreDataPropertySlot(
499 : spec->AddStoreDataPropertyInLiteralICSlot());
500 : }
501 752293 : }
502 :
503 :
504 4078660 : void ObjectLiteral::CalculateEmitStore(Zone* zone) {
505 : const auto GETTER = ObjectLiteral::Property::GETTER;
506 : const auto SETTER = ObjectLiteral::Property::SETTER;
507 :
508 : ZoneAllocationPolicy allocator(zone);
509 :
510 : CustomMatcherZoneHashMap table(
511 : Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
512 3326367 : for (int i = properties()->length() - 1; i >= 0; i--) {
513 5147528 : ObjectLiteral::Property* property = properties()->at(i);
514 5105866 : if (property->is_computed_name()) continue;
515 2571843 : if (property->kind() == ObjectLiteral::Property::PROTOTYPE) continue;
516 2531792 : Literal* literal = property->key()->AsLiteral();
517 : DCHECK(!literal->IsNullLiteral());
518 :
519 : // If there is an existing entry do not emit a store unless the previous
520 : // entry was also an accessor.
521 2531792 : uint32_t hash = literal->Hash();
522 5063584 : ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
523 2531792 : if (entry->value != NULL) {
524 : auto previous_kind =
525 : static_cast<ObjectLiteral::Property*>(entry->value)->kind();
526 2459 : if (!((property->kind() == GETTER && previous_kind == SETTER) ||
527 2487 : (property->kind() == SETTER && previous_kind == GETTER))) {
528 : property->set_emit_store(false);
529 : }
530 : }
531 2531792 : entry->value = property;
532 : }
533 752293 : }
534 :
535 :
536 17359715 : bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) {
537 24883830 : return property != NULL &&
538 4917800 : property->kind() != ObjectLiteral::Property::PROTOTYPE;
539 : }
540 :
541 4339082 : void ObjectLiteral::InitDepthAndFlags() {
542 2051272 : if (depth_ > 0) return;
543 :
544 : int position = 0;
545 : // Accumulate the value in local variables and store it at the end.
546 : bool is_simple = true;
547 : int depth_acc = 1;
548 : uint32_t max_element_index = 0;
549 : uint32_t elements = 0;
550 5878632 : for (int i = 0; i < properties()->length(); i++) {
551 2567070 : ObjectLiteral::Property* property = properties()->at(i);
552 2567070 : if (!IsBoilerplateProperty(property)) {
553 : is_simple = false;
554 40001 : continue;
555 : }
556 :
557 2527069 : if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
558 : DCHECK(property->is_computed_name());
559 : is_simple = false;
560 1884 : break;
561 : }
562 : DCHECK(!property->is_computed_name());
563 :
564 7575555 : MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
565 2525185 : if (m_literal != NULL) {
566 254980 : m_literal->InitDepthAndFlags();
567 254980 : if (m_literal->depth() >= depth_acc) depth_acc = m_literal->depth() + 1;
568 : }
569 :
570 7575554 : const AstValue* key = property->key()->AsLiteral()->raw_value();
571 : Expression* value = property->value();
572 :
573 2525185 : bool is_compile_time_value = CompileTimeValue::IsCompileTimeValue(value);
574 :
575 : // Ensure objects that may, at any point in time, contain fields with double
576 : // representation are always treated as nested objects. This is true for
577 : // computed fields, and smi and double literals.
578 : // TODO(verwaest): Remove once we can store them inline.
579 7574012 : if (FLAG_track_double_fields &&
580 4042500 : (value->IsNumberLiteral() || !is_compile_time_value)) {
581 3171544 : bit_field_ = MayStoreDoublesField::update(bit_field_, true);
582 : }
583 :
584 2525184 : is_simple = is_simple && is_compile_time_value;
585 :
586 : // Keep track of the number of elements in the object literal and
587 : // the largest element index. If the largest element index is
588 : // much larger than the number of elements, creating an object
589 : // literal with fast elements will be a waste of space.
590 2525184 : uint32_t element_index = 0;
591 5034375 : if (key->IsString() && key->AsString()->AsArrayIndex(&element_index)) {
592 452 : max_element_index = Max(element_index, max_element_index);
593 452 : elements++;
594 2524732 : } else if (key->ToUint32(&element_index) && element_index != kMaxUInt32) {
595 15993 : max_element_index = Max(element_index, max_element_index);
596 15993 : elements++;
597 : }
598 :
599 : // Increment the position for the key and the value.
600 2525185 : position += 2;
601 : }
602 :
603 : bit_field_ = FastElementsField::update(
604 : bit_field_,
605 1496520 : (max_element_index <= 32) || ((2 * elements) >= max_element_index));
606 1496520 : bit_field_ = HasElementsField::update(bit_field_, elements > 0);
607 :
608 : set_is_simple(is_simple);
609 : set_depth(depth_acc);
610 : }
611 :
612 6965733 : void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
613 1340450 : if (!constant_properties_.is_null()) return;
614 :
615 : int index_keys = 0;
616 : bool has_seen_proto = false;
617 5628251 : for (int i = 0; i < properties()->length(); i++) {
618 2479358 : ObjectLiteral::Property* property = properties()->at(i);
619 2479358 : if (!IsBoilerplateProperty(property)) {
620 : has_seen_proto = true;
621 30818 : continue;
622 : }
623 2449285 : if (property->is_computed_name()) {
624 : continue;
625 : }
626 :
627 4897080 : Handle<Object> key = property->key()->AsLiteral()->value();
628 :
629 2448540 : uint32_t element_index = 0;
630 7329728 : if (key->ToArrayIndex(&element_index) ||
631 2432648 : (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index))) {
632 16338 : index_keys++;
633 : }
634 : }
635 :
636 : Handle<BoilerplateDescription> constant_properties =
637 : isolate->factory()->NewBoilerplateDescription(boilerplate_properties_,
638 : properties()->length(),
639 669535 : index_keys, has_seen_proto);
640 :
641 : int position = 0;
642 6293230 : for (int i = 0; i < properties()->length(); i++) {
643 2477687 : ObjectLiteral::Property* property = properties()->at(i);
644 2477687 : if (!IsBoilerplateProperty(property)) {
645 30067 : continue;
646 : }
647 :
648 2447620 : if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
649 : DCHECK(property->is_computed_name());
650 607 : break;
651 : }
652 : DCHECK(!property->is_computed_name());
653 :
654 7341038 : MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
655 2447013 : if (m_literal != NULL) {
656 251761 : m_literal->BuildConstants(isolate);
657 : }
658 :
659 : // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
660 : // value for COMPUTED properties, the real value is filled in at
661 : // runtime. The enumeration order is maintained.
662 4894025 : Handle<Object> key = property->key()->AsLiteral()->value();
663 2447012 : Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
664 :
665 2447012 : uint32_t element_index = 0;
666 4878270 : if (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index)) {
667 416 : key = isolate->factory()->NewNumberFromUint(element_index);
668 2462350 : } else if (key->IsNumber() && !key->ToArrayIndex(&element_index)) {
669 0 : key = isolate->factory()->NumberToString(key);
670 : }
671 :
672 : // Add name, value pair to the fixed array.
673 4894024 : constant_properties->set(position++, *key);
674 4894024 : constant_properties->set(position++, *value);
675 : }
676 :
677 669535 : constant_properties_ = constant_properties;
678 : }
679 :
680 634180 : bool ObjectLiteral::IsFastCloningSupported() const {
681 : // The FastCloneShallowObject builtin doesn't copy elements, and object
682 : // literals don't support copy-on-write (COW) elements for now.
683 : // TODO(mvstanton): make object literals support COW elements.
684 1124850 : return fast_elements() && has_shallow_properties() &&
685 : properties_count() <=
686 491143 : ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
687 : }
688 :
689 0 : ElementsKind ArrayLiteral::constant_elements_kind() const {
690 0 : return static_cast<ElementsKind>(constant_elements()->elements_kind());
691 : }
692 :
693 12364156 : void ArrayLiteral::InitDepthAndFlags() {
694 : DCHECK_LT(first_spread_index_, 0);
695 :
696 764494 : if (depth_ > 0) return;
697 :
698 309166 : int constants_length = values()->length();
699 :
700 : // Fill in the literals.
701 : bool is_simple = true;
702 : int depth_acc = 1;
703 : int array_index = 0;
704 11981909 : for (; array_index < constants_length; array_index++) {
705 11672743 : Expression* element = values()->at(array_index);
706 : DCHECK(!element->IsSpread());
707 : MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
708 11672743 : if (m_literal != NULL) {
709 97157 : m_literal->InitDepthAndFlags();
710 97157 : if (m_literal->depth() + 1 > depth_acc) {
711 46306 : depth_acc = m_literal->depth() + 1;
712 : }
713 : }
714 :
715 11672743 : if (!CompileTimeValue::IsCompileTimeValue(element)) {
716 : is_simple = false;
717 : }
718 : }
719 :
720 : set_is_simple(is_simple);
721 : set_depth(depth_acc);
722 : }
723 :
724 12188749 : void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
725 : DCHECK_LT(first_spread_index_, 0);
726 :
727 293194 : if (!constant_elements_.is_null()) return;
728 :
729 293194 : int constants_length = values()->length();
730 : ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
731 : Handle<FixedArray> fixed_array =
732 293194 : isolate->factory()->NewFixedArrayWithHoles(constants_length);
733 :
734 : // Fill in the literals.
735 : bool is_holey = false;
736 : int array_index = 0;
737 11895555 : for (; array_index < constants_length; array_index++) {
738 11602361 : Expression* element = values()->at(array_index);
739 : DCHECK(!element->IsSpread());
740 : MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
741 11602361 : if (m_literal != NULL) {
742 95919 : m_literal->BuildConstants(isolate);
743 : }
744 :
745 : // New handle scope here, needs to be after BuildContants().
746 : HandleScope scope(isolate);
747 11895555 : Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
748 11602361 : if (boilerplate_value->IsTheHole(isolate)) {
749 : is_holey = true;
750 : continue;
751 : }
752 :
753 10178271 : if (boilerplate_value->IsUninitialized(isolate)) {
754 : boilerplate_value = handle(Smi::kZero, isolate);
755 : }
756 :
757 : kind = GetMoreGeneralElementsKind(kind,
758 10178271 : boilerplate_value->OptimalElementsKind());
759 10178271 : fixed_array->set(array_index, *boilerplate_value);
760 : }
761 :
762 293194 : if (is_holey) kind = GetHoleyElementsKind(kind);
763 :
764 : // Simple and shallow arrays can be lazily copied, we transform the
765 : // elements array to a copy-on-write array.
766 510648 : if (is_simple() && depth() == 1 && array_index > 0 &&
767 : IsFastSmiOrObjectElementsKind(kind)) {
768 128260 : fixed_array->set_map(isolate->heap()->fixed_cow_array_map());
769 : }
770 :
771 : Handle<FixedArrayBase> elements = fixed_array;
772 293194 : if (IsFastDoubleElementsKind(kind)) {
773 : ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
774 3063 : elements = isolate->factory()->NewFixedDoubleArray(constants_length);
775 : // We are copying from non-fast-double to fast-double.
776 : ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
777 6126 : accessor->CopyElements(fixed_array, from_kind, elements, constants_length);
778 : }
779 :
780 : // Remember both the literal's constant values as well as the ElementsKind.
781 : Handle<ConstantElementsPair> literals =
782 293194 : isolate->factory()->NewConstantElementsPair(kind, elements);
783 :
784 293194 : constant_elements_ = literals;
785 : }
786 :
787 445571 : bool ArrayLiteral::IsFastCloningSupported() const {
788 445571 : return depth() <= 1 &&
789 219984 : values()->length() <=
790 225587 : ConstructorBuiltins::kMaximumClonedShallowArrayElements;
791 : }
792 :
793 3324 : void ArrayLiteral::RewindSpreads() {
794 3324 : values_->Rewind(first_spread_index_);
795 3324 : first_spread_index_ = -1;
796 3324 : }
797 :
798 309216 : void ArrayLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
799 : LanguageMode language_mode,
800 11315557 : FeedbackSlotCache* cache) {
801 : MaterializedLiteral::AssignFeedbackSlots(spec, language_mode, cache);
802 :
803 : // This logic that computes the number of slots needed for vector store
804 : // ics must mirror FullCodeGenerator::VisitArrayLiteral.
805 22631114 : for (int array_index = 0; array_index < values()->length(); array_index++) {
806 11088536 : Expression* subexpr = values()->at(array_index);
807 : DCHECK(!subexpr->IsSpread());
808 11088536 : if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
809 :
810 : // We'll reuse the same literal slot for all of the non-constant
811 : // subexpressions that use a keyed store IC.
812 82195 : literal_slot_ = spec->AddKeyedStoreICSlot(language_mode);
813 391411 : return;
814 : }
815 : }
816 :
817 :
818 14049373 : Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
819 : Isolate* isolate) {
820 14049374 : if (expression->IsLiteral()) {
821 25669680 : return expression->AsLiteral()->value();
822 : }
823 1214534 : if (CompileTimeValue::IsCompileTimeValue(expression)) {
824 294850 : return CompileTimeValue::GetValue(isolate, expression);
825 : }
826 919684 : return isolate->factory()->uninitialized_value();
827 : }
828 :
829 352137 : void MaterializedLiteral::InitDepthAndFlags() {
830 352137 : if (IsArrayLiteral()) {
831 146062 : return AsArrayLiteral()->InitDepthAndFlags();
832 : }
833 279106 : if (IsObjectLiteral()) {
834 546686 : return AsObjectLiteral()->InitDepthAndFlags();
835 : }
836 : DCHECK(IsRegExpLiteral());
837 : DCHECK_LE(1, depth()); // Depth should be initialized.
838 : }
839 :
840 347680 : void MaterializedLiteral::BuildConstants(Isolate* isolate) {
841 347680 : if (IsArrayLiteral()) {
842 143432 : return AsArrayLiteral()->BuildConstantElements(isolate);
843 : }
844 275964 : if (IsObjectLiteral()) {
845 540448 : return AsObjectLiteral()->BuildConstantProperties(isolate);
846 : }
847 : DCHECK(IsRegExpLiteral());
848 : }
849 :
850 :
851 186448 : void UnaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
852 : // TODO(olivf) If this Operation is used in a test context, then the
853 : // expression has a ToBoolean stub and we want to collect the type
854 : // information. However the GraphBuilder expects it to be on the instruction
855 : // corresponding to the TestContext, therefore we have to store it here and
856 : // not on the operand.
857 186448 : set_to_boolean_types(oracle->ToBooleanTypes(expression()->test_id()));
858 186448 : }
859 :
860 :
861 149557 : void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
862 : // TODO(olivf) If this Operation is used in a test context, then the right
863 : // hand side has a ToBoolean stub and we want to collect the type information.
864 : // However the GraphBuilder expects it to be on the instruction corresponding
865 : // to the TestContext, therefore we have to store it here and not on the
866 : // right hand operand.
867 149557 : set_to_boolean_types(oracle->ToBooleanTypes(right()->test_id()));
868 149557 : }
869 :
870 3750940 : void BinaryOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
871 : LanguageMode language_mode,
872 3750940 : FeedbackSlotCache* cache) {
873 : // Feedback vector slot is only used by interpreter for binary operations.
874 : // Full-codegen uses AstId to record type feedback.
875 3750940 : switch (op()) {
876 : // Comma, logical_or and logical_and do not collect type feedback.
877 : case Token::COMMA:
878 : case Token::AND:
879 : case Token::OR:
880 : return;
881 : default:
882 2774743 : feedback_slot_ = spec->AddInterpreterBinaryOpICSlot();
883 2774743 : return;
884 : }
885 : }
886 :
887 : static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
888 : // Add is not commutative due to potential for string addition.
889 639108 : return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
890 : op == Token::BIT_XOR;
891 : }
892 :
893 : // Check for the pattern: x + 1.
894 1014905 : static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
895 : Expression** expr, Smi** literal) {
896 1014905 : if (right->IsSmiLiteral()) {
897 307542 : *expr = left;
898 615084 : *literal = right->AsLiteral()->AsSmiLiteral();
899 307542 : return true;
900 : }
901 : return false;
902 : }
903 :
904 931383 : bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
905 639108 : Smi** literal) {
906 1570491 : return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
907 83522 : (IsCommutativeOperationWithSmiLiteral(op()) &&
908 1014904 : MatchSmiLiteralOperation(right_, left_, subexpr, literal));
909 : }
910 :
911 4294358 : static bool IsTypeof(Expression* expr) {
912 4782472 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
913 4782473 : return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
914 : }
915 :
916 2302959 : void CompareOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
917 : LanguageMode language_mode,
918 2302959 : FeedbackSlotCache* cache_) {
919 : // Feedback vector slot is only used by interpreter for binary operations.
920 : // Full-codegen uses AstId to record type feedback.
921 2302959 : switch (op()) {
922 : // instanceof and in do not collect type feedback.
923 : case Token::INSTANCEOF:
924 : case Token::IN:
925 2302959 : return;
926 : default:
927 2261572 : feedback_slot_ = spec->AddInterpreterCompareICSlot();
928 : }
929 : }
930 :
931 : // Check for the pattern: typeof <expression> equals <string literal>.
932 4294359 : static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
933 : Expression* right, Expression** expr,
934 : Literal** literal) {
935 4580349 : if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
936 571980 : *expr = left->AsUnaryOperation()->expression();
937 571980 : *literal = right->AsLiteral();
938 285990 : return true;
939 : }
940 : return false;
941 : }
942 :
943 2290124 : bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
944 4294361 : Literal** literal) {
945 6584485 : return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
946 6298597 : MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
947 : }
948 :
949 :
950 4006424 : static bool IsVoidOfLiteral(Expression* expr) {
951 4320709 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
952 201469 : return maybe_unary != NULL &&
953 4119240 : maybe_unary->op() == Token::VOID &&
954 4006424 : maybe_unary->expression()->IsLiteral();
955 : }
956 :
957 :
958 : // Check for the pattern: void <literal> equals <expression> or
959 : // undefined equals <expression>
960 4006424 : static bool MatchLiteralCompareUndefined(Expression* left,
961 : Token::Value op,
962 : Expression* right,
963 : Expression** expr) {
964 4119232 : if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
965 111420 : *expr = right;
966 111420 : return true;
967 : }
968 3942267 : if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
969 47191 : *expr = right;
970 47191 : return true;
971 : }
972 : return false;
973 : }
974 :
975 6010558 : bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
976 6010557 : return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
977 6008716 : MatchLiteralCompareUndefined(right_, op(), left_, expr);
978 : }
979 :
980 :
981 : // Check for the pattern: null equals <expression>
982 3689852 : static bool MatchLiteralCompareNull(Expression* left,
983 : Token::Value op,
984 : Expression* right,
985 : Expression** expr) {
986 3794824 : if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
987 103523 : *expr = right;
988 103523 : return true;
989 : }
990 : return false;
991 : }
992 :
993 :
994 5535373 : bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
995 5535374 : return MatchLiteralCompareNull(left_, op(), right_, expr) ||
996 5534184 : MatchLiteralCompareNull(right_, op(), left_, expr);
997 : }
998 :
999 :
1000 : // ----------------------------------------------------------------------------
1001 : // Recording of type feedback
1002 :
1003 : // TODO(rossberg): all RecordTypeFeedback functions should disappear
1004 : // once we use the common type field in the AST consistently.
1005 :
1006 1357149 : void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
1007 1357149 : if (IsUnaryOperation()) {
1008 372896 : AsUnaryOperation()->RecordToBooleanTypeFeedback(oracle);
1009 1170701 : } else if (IsBinaryOperation()) {
1010 299114 : AsBinaryOperation()->RecordToBooleanTypeFeedback(oracle);
1011 : } else {
1012 1021144 : set_to_boolean_types(oracle->ToBooleanTypes(test_id()));
1013 : }
1014 1357149 : }
1015 :
1016 805234 : SmallMapList* Expression::GetReceiverTypes() {
1017 1610468 : switch (node_type()) {
1018 : #define NODE_LIST(V) \
1019 : PROPERTY_NODE_LIST(V) \
1020 : V(Call)
1021 : #define GENERATE_CASE(Node) \
1022 : case k##Node: \
1023 : return static_cast<Node*>(this)->GetReceiverTypes();
1024 72372 : NODE_LIST(GENERATE_CASE)
1025 : #undef NODE_LIST
1026 : #undef GENERATE_CASE
1027 : default:
1028 0 : UNREACHABLE();
1029 : return nullptr;
1030 : }
1031 : }
1032 :
1033 24584 : KeyedAccessStoreMode Expression::GetStoreMode() const {
1034 49168 : switch (node_type()) {
1035 : #define GENERATE_CASE(Node) \
1036 : case k##Node: \
1037 : return static_cast<const Node*>(this)->GetStoreMode();
1038 5235 : PROPERTY_NODE_LIST(GENERATE_CASE)
1039 : #undef GENERATE_CASE
1040 : default:
1041 0 : UNREACHABLE();
1042 : return STANDARD_STORE;
1043 : }
1044 : }
1045 :
1046 107304 : IcCheckType Expression::GetKeyType() const {
1047 214608 : switch (node_type()) {
1048 : #define GENERATE_CASE(Node) \
1049 : case k##Node: \
1050 : return static_cast<const Node*>(this)->GetKeyType();
1051 107304 : PROPERTY_NODE_LIST(GENERATE_CASE)
1052 : #undef GENERATE_CASE
1053 : default:
1054 0 : UNREACHABLE();
1055 : return PROPERTY;
1056 : }
1057 : }
1058 :
1059 805234 : bool Expression::IsMonomorphic() const {
1060 1610468 : switch (node_type()) {
1061 : #define GENERATE_CASE(Node) \
1062 : case k##Node: \
1063 : return static_cast<const Node*>(this)->IsMonomorphic();
1064 596745 : PROPERTY_NODE_LIST(GENERATE_CASE)
1065 208489 : CALL_NODE_LIST(GENERATE_CASE)
1066 : #undef GENERATE_CASE
1067 : default:
1068 0 : UNREACHABLE();
1069 : return false;
1070 : }
1071 : }
1072 :
1073 4171566 : void Call::AssignFeedbackSlots(FeedbackVectorSpec* spec,
1074 : LanguageMode language_mode,
1075 : FeedbackSlotCache* cache) {
1076 4171578 : ic_slot_ = spec->AddCallICSlot();
1077 4171578 : }
1078 :
1079 8293366 : Call::CallType Call::GetCallType() const {
1080 5550055 : VariableProxy* proxy = expression()->AsVariableProxy();
1081 3575407 : if (proxy != NULL) {
1082 1974658 : if (proxy->var()->IsUnallocated()) {
1083 : return GLOBAL_CALL;
1084 995659 : } else if (proxy->var()->IsLookupSlot()) {
1085 : // Calls going through 'with' always use DYNAMIC rather than DYNAMIC_LOCAL
1086 : // or DYNAMIC_GLOBAL.
1087 235371 : return proxy->var()->mode() == DYNAMIC ? WITH_CALL : OTHER_CALL;
1088 : }
1089 : }
1090 :
1091 4722070 : if (expression()->IsSuperCallReference()) return SUPER_CALL;
1092 :
1093 3824035 : Property* property = expression()->AsProperty();
1094 2356938 : if (property != nullptr) {
1095 1467102 : bool is_super = property->IsSuperAccess();
1096 1467103 : if (property->key()->IsPropertyName()) {
1097 1457934 : return is_super ? NAMED_SUPER_PROPERTY_CALL : NAMED_PROPERTY_CALL;
1098 : } else {
1099 9169 : return is_super ? KEYED_SUPER_PROPERTY_CALL : KEYED_PROPERTY_CALL;
1100 : }
1101 : }
1102 :
1103 : return OTHER_CALL;
1104 : }
1105 :
1106 535223 : CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements,
1107 : int pos)
1108 : : Expression(pos, kCaseClause),
1109 : label_(label),
1110 : statements_(statements),
1111 1605669 : compare_type_(AstType::None()) {}
1112 :
1113 243390 : void CaseClause::AssignFeedbackSlots(FeedbackVectorSpec* spec,
1114 : LanguageMode language_mode,
1115 : FeedbackSlotCache* cache) {
1116 243390 : feedback_slot_ = spec->AddInterpreterCompareICSlot();
1117 243390 : }
1118 :
1119 2537594 : uint32_t Literal::Hash() {
1120 2537594 : return raw_value()->IsString()
1121 2521441 : ? raw_value()->AsString()->hash()
1122 5091341 : : ComputeLongHash(double_to_uint64(raw_value()->AsNumber()));
1123 : }
1124 :
1125 :
1126 : // static
1127 99854 : bool Literal::Match(void* literal1, void* literal2) {
1128 99854 : const AstValue* x = static_cast<Literal*>(literal1)->raw_value();
1129 99126 : const AstValue* y = static_cast<Literal*>(literal2)->raw_value();
1130 298834 : return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) ||
1131 728 : (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
1132 : }
1133 :
1134 0 : const char* CallRuntime::debug_name() {
1135 : #ifdef DEBUG
1136 : return is_jsruntime() ? NameForNativeContextIntrinsicIndex(context_index_)
1137 : : function_->name;
1138 : #else
1139 0 : return is_jsruntime() ? "(context function)" : function_->name;
1140 : #endif // DEBUG
1141 : }
1142 :
1143 : } // namespace internal
1144 : } // namespace v8
|