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 293965 : IterationStatement* AstNode::AsIterationStatement() {
66 293965 : 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 36294643 : MaterializedLiteral* AstNode::AsMaterializedLiteral() {
83 36294643 : switch (node_type()) {
84 40110 : LITERAL_NODE_LIST(RETURN_NODE);
85 : default:
86 : return nullptr;
87 : }
88 : }
89 :
90 : #undef RETURN_NODE
91 :
92 1105956 : bool Expression::IsSmiLiteral() const {
93 3288646 : return IsLiteral() && AsLiteral()->raw_value()->IsSmi();
94 : }
95 :
96 2516912 : bool Expression::IsNumberLiteral() const {
97 8500870 : return IsLiteral() && AsLiteral()->raw_value()->IsNumber();
98 : }
99 :
100 1819225 : bool Expression::IsStringLiteral() const {
101 5360419 : return IsLiteral() && AsLiteral()->raw_value()->IsString();
102 : }
103 :
104 28706017 : bool Expression::IsPropertyName() const {
105 102400046 : return IsLiteral() && AsLiteral()->IsPropertyName();
106 : }
107 :
108 3689271 : bool Expression::IsNullLiteral() const {
109 7378542 : if (!IsLiteral()) return false;
110 2309560 : return AsLiteral()->raw_value()->IsNull();
111 : }
112 :
113 4423075 : bool Expression::IsUndefinedLiteral() const {
114 5882827 : if (IsLiteral() && AsLiteral()->raw_value()->IsUndefined()) return true;
115 :
116 6008678 : const VariableProxy* var_proxy = AsVariableProxy();
117 4388501 : 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 3337508 : return var != NULL && var->IsUnallocated() &&
122 1717331 : var_proxy->raw_name()->IsOneByteEqualTo("undefined");
123 : }
124 :
125 2497105 : bool Expression::ToBooleanIsTrue() const {
126 5022192 : return IsLiteral() && AsLiteral()->ToBooleanIsTrue();
127 : }
128 :
129 2498643 : bool Expression::ToBooleanIsFalse() const {
130 5032934 : return IsLiteral() && AsLiteral()->ToBooleanIsFalse();
131 : }
132 :
133 11738046 : 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 11738046 : if (IsRewritableExpression()) return false;
138 16849045 : return IsProperty() ||
139 10212078 : (IsVariableProxy() && AsVariableProxy()->IsValidReferenceExpression());
140 : }
141 :
142 0 : bool Expression::IsValidReferenceExpressionOrThis() const {
143 0 : return IsValidReferenceExpression() ||
144 0 : (IsVariableProxy() && AsVariableProxy()->is_this());
145 : }
146 :
147 19124041 : bool Expression::IsAnonymousFunctionDefinition() const {
148 1533539 : return (IsFunctionLiteral() &&
149 37430079 : AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
150 3765 : (IsDoExpression() &&
151 19127803 : AsDoExpression()->IsAnonymousFunctionDefinition());
152 : }
153 :
154 11034 : void Expression::MarkTail() {
155 11034 : if (IsConditional()) {
156 280 : AsConditional()->MarkTail();
157 10894 : } else if (IsCall()) {
158 3669 : AsCall()->MarkTail();
159 7225 : } else if (IsBinaryOperation()) {
160 2484 : AsBinaryOperation()->MarkTail();
161 : }
162 11034 : }
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 53372407 : bool Statement::IsJump() const {
171 68933486 : 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 26412513 : JUMP_NODE_LIST(GENERATE_CASE)
183 : #undef GENERATE_CASE
184 : #undef JUMP_NODE_LIST
185 : default:
186 936429 : return false;
187 : }
188 : }
189 :
190 27503046 : VariableProxy::VariableProxy(Variable* var, int start_position)
191 : : Expression(start_position, kVariableProxy),
192 : raw_name_(var->raw_name()),
193 13751523 : next_unresolved_(nullptr) {
194 : bit_field_ |= IsThisField::encode(var->is_this()) |
195 : IsAssignedField::encode(false) |
196 : IsResolvedField::encode(false) |
197 13751523 : HoleCheckModeField::encode(HoleCheckMode::kElided);
198 : BindTo(var);
199 13751523 : }
200 :
201 124131731 : VariableProxy::VariableProxy(const AstRawString* name,
202 : VariableKind variable_kind, int start_position)
203 : : Expression(start_position, kVariableProxy),
204 : raw_name_(name),
205 124131731 : next_unresolved_(nullptr) {
206 124131731 : bit_field_ |= IsThisField::encode(variable_kind == THIS_VARIABLE) |
207 : IsAssignedField::encode(false) |
208 : IsResolvedField::encode(false) |
209 124131731 : HoleCheckModeField::encode(HoleCheckMode::kElided);
210 124131731 : }
211 :
212 2532352 : VariableProxy::VariableProxy(const VariableProxy* copy_from)
213 : : Expression(copy_from->position(), kVariableProxy),
214 5064704 : next_unresolved_(nullptr) {
215 2532352 : bit_field_ = copy_from->bit_field_;
216 : DCHECK(!copy_from->is_resolved());
217 2532352 : raw_name_ = copy_from->raw_name_;
218 2532352 : }
219 :
220 93187547 : 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 106939070 : if (is_assigned()) var->set_maybe_assigned();
226 93187547 : }
227 :
228 28601512 : void VariableProxy::AssignFeedbackSlots(FeedbackVectorSpec* spec,
229 : TypeofMode typeof_mode,
230 3030098 : FeedbackSlotCache* cache) {
231 28601512 : if (UsesVariableFeedbackSlot()) {
232 : // VariableProxies that point to the same Variable within a function can
233 : // make their loads from the same IC slot.
234 5975742 : if (var()->IsUnallocated() || var()->mode() == DYNAMIC_GLOBAL) {
235 4769107 : FeedbackSlot slot = cache->Get(typeof_mode, var());
236 4769104 : if (!slot.IsInvalid()) {
237 1739008 : variable_feedback_slot_ = slot;
238 30340516 : return;
239 : }
240 3030098 : 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 10904350 : static void AssignVectorSlots(Expression* expr, FeedbackVectorSpec* spec,
249 : LanguageMode language_mode,
250 : FeedbackSlot* out_slot) {
251 10904350 : Property* property = expr->AsProperty();
252 10904349 : LhsKind assign_type = Property::GetAssignType(property);
253 : // TODO(ishell): consider using ICSlotCache for variables here.
254 19049712 : if (assign_type == VARIABLE &&
255 8145362 : expr->AsVariableProxy()->var()->IsUnallocated()) {
256 997762 : *out_slot = spec->AddStoreGlobalICSlot(language_mode);
257 :
258 9906590 : } else if (assign_type == NAMED_PROPERTY) {
259 2547940 : *out_slot = spec->AddStoreICSlot(language_mode);
260 :
261 7358650 : } else if (assign_type == KEYED_PROPERTY) {
262 210212 : *out_slot = spec->AddKeyedStoreICSlot(language_mode);
263 : }
264 10904352 : }
265 :
266 11519 : void ForInStatement::AssignFeedbackSlots(FeedbackVectorSpec* spec,
267 : LanguageMode language_mode,
268 11519 : FeedbackSlotCache* cache) {
269 23038 : AssignVectorSlots(each(), spec, language_mode, &each_slot_);
270 11519 : for_in_feedback_slot_ = spec->AddGeneralSlot();
271 11519 : }
272 :
273 28083326 : Assignment::Assignment(Token::Value op, Expression* target, Expression* value,
274 : int pos)
275 : : Expression(pos, kAssignment),
276 : target_(target),
277 : value_(value),
278 28083326 : binary_operation_(NULL) {
279 : bit_field_ |= IsUninitializedField::encode(false) |
280 : KeyTypeField::encode(ELEMENT) |
281 28083326 : StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op);
282 28083326 : }
283 :
284 10617531 : void Assignment::AssignFeedbackSlots(FeedbackVectorSpec* spec,
285 : LanguageMode language_mode,
286 10617531 : FeedbackSlotCache* cache) {
287 21235062 : AssignVectorSlots(target(), spec, language_mode, &slot_);
288 10617535 : }
289 :
290 275299 : void CountOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
291 : LanguageMode language_mode,
292 275299 : FeedbackSlotCache* cache) {
293 550598 : 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 275299 : binary_operation_slot_ = spec->AddInterpreterBinaryOpICSlot();
297 275299 : }
298 :
299 :
300 710403 : Token::Value Assignment::binary_op() const {
301 710403 : 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 7853 : case Token::ASSIGN_SAR: return Token::SAR;
307 7117 : case Token::ASSIGN_SHR: return Token::SHR;
308 630756 : case Token::ASSIGN_ADD: return Token::ADD;
309 11448 : case Token::ASSIGN_SUB: return Token::SUB;
310 7951 : 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 5454100 : bool FunctionLiteral::ShouldEagerCompile() const {
319 5454100 : return scope()->ShouldEagerCompile();
320 : }
321 :
322 1096608 : void FunctionLiteral::SetShouldEagerCompile() {
323 1096608 : scope()->set_should_eager_compile();
324 1096611 : }
325 :
326 6231074 : bool FunctionLiteral::AllowsLazyCompilation() {
327 6231074 : return scope()->AllowsLazyCompilation();
328 : }
329 :
330 :
331 12913471 : int FunctionLiteral::start_position() const {
332 12913471 : return scope()->start_position();
333 : }
334 :
335 :
336 9743015 : int FunctionLiteral::end_position() const {
337 9743015 : return scope()->end_position();
338 : }
339 :
340 :
341 11603971 : LanguageMode FunctionLiteral::language_mode() const {
342 11603971 : return scope()->language_mode();
343 : }
344 :
345 28021755 : FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); }
346 :
347 2450875 : bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
348 4901750 : if (expr == nullptr || !expr->IsFunctionLiteral()) return false;
349 : DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope());
350 3715522 : return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
351 : }
352 :
353 220772 : ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
354 : Kind kind, bool is_computed_name)
355 : : LiteralProperty(key, value, is_computed_name),
356 : kind_(kind),
357 441544 : emit_store_(true) {}
358 :
359 9363251 : ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
360 : Expression* key, Expression* value,
361 : bool is_computed_name)
362 4689392 : : LiteralProperty(key, value, is_computed_name), emit_store_(true) {
363 9363254 : if (!is_computed_name &&
364 : key->AsLiteral()->raw_value()->EqualsString(
365 9347721 : ast_value_factory->proto_string())) {
366 92485 : kind_ = PROTOTYPE;
367 9193820 : } else if (value_->AsMaterializedLiteral() != NULL) {
368 296568 : kind_ = MATERIALIZED_LITERAL;
369 4300342 : } else if (value_->IsLiteral()) {
370 2045957 : kind_ = CONSTANT;
371 : } else {
372 2254385 : kind_ = COMPUTED;
373 : }
374 4689395 : }
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 43566 : void ClassLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
401 : LanguageMode language_mode,
402 390594 : FeedbackSlotCache* cache) {
403 : // This logic that computes the number of slots needed for vector store
404 : // ICs must mirror BytecodeGenerator::VisitClassLiteral.
405 43566 : if (FunctionLiteral::NeedsHomeObject(constructor())) {
406 1204 : home_object_slot_ = spec->AddStoreICSlot(language_mode);
407 : }
408 :
409 43566 : if (NeedsProxySlot()) {
410 0 : proxy_slot_ = spec->AddStoreICSlot(language_mode);
411 : }
412 :
413 650490 : 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 43566 : }
423 :
424 4346189 : bool ObjectLiteral::Property::IsCompileTimeValue() const {
425 4346189 : return kind_ == CONSTANT ||
426 361919 : (kind_ == MATERIALIZED_LITERAL &&
427 4708108 : 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 1176508 : bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
436 :
437 750142 : void ObjectLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
438 : LanguageMode language_mode,
439 4067522 : 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 6626638 : for (; property_index < properties()->length(); property_index++) {
446 3186352 : ObjectLiteral::Property* property = properties()->at(property_index);
447 3807643 : if (property->is_computed_name()) break;
448 2563177 : if (property->IsCompileTimeValue()) continue;
449 :
450 621291 : Literal* key = property->key()->AsLiteral();
451 : Expression* value = property->value();
452 621291 : 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 575201 : if (key->IsStringLiteral()) {
462 574433 : if (property->emit_store()) {
463 : property->SetSlot(spec->AddStoreOwnICSlot());
464 574220 : if (FunctionLiteral::NeedsHomeObject(value)) {
465 : property->SetSlot(spec->AddStoreICSlot(language_mode), 1);
466 : }
467 : }
468 : break;
469 : }
470 768 : 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 758264 : 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 750142 : }
502 :
503 :
504 4067522 : 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 3317380 : for (int i = properties()->length() - 1; i >= 0; i--) {
513 5133856 : ObjectLiteral::Property* property = properties()->at(i);
514 5092297 : if (property->is_computed_name()) continue;
515 2565007 : if (property->kind() == ObjectLiteral::Property::PROTOTYPE) continue;
516 2525059 : 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 2525059 : uint32_t hash = literal->Hash();
522 5050118 : ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
523 2525059 : 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 2525059 : entry->value = property;
532 : }
533 750142 : }
534 :
535 :
536 17324440 : bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) {
537 24828555 : return property != NULL &&
538 4910163 : property->kind() != ObjectLiteral::Property::PROTOTYPE;
539 : }
540 :
541 4326464 : void ObjectLiteral::InitDepthAndFlags() {
542 2044010 : 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 5862809 : for (int i = 0; i < properties()->length(); i++) {
551 2560234 : ObjectLiteral::Property* property = properties()->at(i);
552 2560234 : if (!IsBoilerplateProperty(property)) {
553 : is_simple = false;
554 39898 : continue;
555 : }
556 :
557 2520336 : 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 7555356 : MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
565 2518452 : if (m_literal != NULL) {
566 253625 : m_literal->InitDepthAndFlags();
567 253625 : if (m_literal->depth() >= depth_acc) depth_acc = m_literal->depth() + 1;
568 : }
569 :
570 7555356 : const AstValue* key = property->key()->AsLiteral()->raw_value();
571 : Expression* value = property->value();
572 :
573 2518452 : 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 7553816 : if (FLAG_track_double_fields &&
580 4030681 : (value->IsNumberLiteral() || !is_compile_time_value)) {
581 3167064 : bit_field_ = MayStoreDoublesField::update(bit_field_, true);
582 : }
583 :
584 2518452 : 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 2518452 : uint32_t element_index = 0;
591 5020973 : if (key->IsString() && key->AsString()->AsArrayIndex(&element_index)) {
592 452 : max_element_index = Max(element_index, max_element_index);
593 452 : elements++;
594 2518000 : } else if (key->ToUint32(&element_index) && element_index != kMaxUInt32) {
595 15931 : max_element_index = Max(element_index, max_element_index);
596 15931 : elements++;
597 : }
598 :
599 : // Increment the position for the key and the value.
600 2518452 : position += 2;
601 : }
602 :
603 : bit_field_ = FastElementsField::update(
604 : bit_field_,
605 1492218 : (max_element_index <= 32) || ((2 * elements) >= max_element_index));
606 1492218 : bit_field_ = HasElementsField::update(bit_field_, elements > 0);
607 :
608 : set_is_simple(is_simple);
609 : set_depth(depth_acc);
610 : }
611 :
612 6946647 : void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
613 1336491 : if (!constant_properties_.is_null()) return;
614 :
615 : int index_keys = 0;
616 : bool has_seen_proto = false;
617 5613116 : for (int i = 0; i < properties()->length(); i++) {
618 2472776 : ObjectLiteral::Property* property = properties()->at(i);
619 2472776 : if (!IsBoilerplateProperty(property)) {
620 : has_seen_proto = true;
621 30783 : continue;
622 : }
623 2442739 : if (property->is_computed_name()) {
624 : continue;
625 : }
626 :
627 4883987 : Handle<Object> key = property->key()->AsLiteral()->value();
628 :
629 2441994 : uint32_t element_index = 0;
630 7310150 : if (key->ToArrayIndex(&element_index) ||
631 2426163 : (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index))) {
632 16276 : index_keys++;
633 : }
634 : }
635 :
636 : Handle<BoilerplateDescription> constant_properties =
637 : isolate->factory()->NewBoilerplateDescription(boilerplate_properties_,
638 : properties()->length(),
639 667564 : index_keys, has_seen_proto);
640 :
641 : int position = 0;
642 6276122 : for (int i = 0; i < properties()->length(); i++) {
643 2471105 : ObjectLiteral::Property* property = properties()->at(i);
644 2471105 : if (!IsBoilerplateProperty(property)) {
645 30032 : continue;
646 : }
647 :
648 2441073 : 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 7321397 : MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
655 2440466 : if (m_literal != NULL) {
656 250410 : 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 4880931 : Handle<Object> key = property->key()->AsLiteral()->value();
663 2440465 : Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
664 :
665 2440464 : uint32_t element_index = 0;
666 4865236 : if (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index)) {
667 416 : key = isolate->factory()->NewNumberFromUint(element_index);
668 2455740 : } 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 4880928 : constant_properties->set(position++, *key);
674 4880928 : constant_properties->set(position++, *value);
675 : }
676 :
677 667563 : constant_properties_ = constant_properties;
678 : }
679 :
680 633328 : 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 1123338 : return fast_elements() && has_shallow_properties() &&
685 : properties_count() <=
686 490483 : 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 12360751 : void ArrayLiteral::InitDepthAndFlags() {
694 : DCHECK_LT(first_spread_index_, 0);
695 :
696 762440 : if (depth_ > 0) return;
697 :
698 308391 : 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 11979531 : for (; array_index < constants_length; array_index++) {
705 11671140 : Expression* element = values()->at(array_index);
706 : DCHECK(!element->IsSpread());
707 : MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
708 11671140 : if (m_literal != NULL) {
709 96780 : m_literal->InitDepthAndFlags();
710 96780 : if (m_literal->depth() + 1 > depth_acc) {
711 46093 : depth_acc = m_literal->depth() + 1;
712 : }
713 : }
714 :
715 11671140 : 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 12185102 : void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
725 : DCHECK_LT(first_spread_index_, 0);
726 :
727 292440 : if (!constant_elements_.is_null()) return;
728 :
729 292440 : int constants_length = values()->length();
730 : ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
731 : Handle<FixedArray> fixed_array =
732 292440 : isolate->factory()->NewFixedArrayWithHoles(constants_length);
733 :
734 : // Fill in the literals.
735 : bool is_holey = false;
736 : int array_index = 0;
737 11892662 : for (; array_index < constants_length; array_index++) {
738 11600222 : Expression* element = values()->at(array_index);
739 : DCHECK(!element->IsSpread());
740 : MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
741 11600222 : if (m_literal != NULL) {
742 95542 : m_literal->BuildConstants(isolate);
743 : }
744 :
745 : // New handle scope here, needs to be after BuildContants().
746 : HandleScope scope(isolate);
747 11892662 : Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
748 11600222 : if (boilerplate_value->IsTheHole(isolate)) {
749 : is_holey = true;
750 : continue;
751 : }
752 :
753 10176191 : if (boilerplate_value->IsUninitialized(isolate)) {
754 : boilerplate_value = handle(Smi::kZero, isolate);
755 : }
756 :
757 : kind = GetMoreGeneralElementsKind(kind,
758 10176191 : boilerplate_value->OptimalElementsKind());
759 10176191 : fixed_array->set(array_index, *boilerplate_value);
760 : }
761 :
762 292440 : 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 509220 : if (is_simple() && depth() == 1 && array_index > 0 &&
767 : IsFastSmiOrObjectElementsKind(kind)) {
768 127662 : fixed_array->set_map(isolate->heap()->fixed_cow_array_map());
769 : }
770 :
771 : Handle<FixedArrayBase> elements = fixed_array;
772 292440 : if (IsFastDoubleElementsKind(kind)) {
773 : ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
774 3045 : 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 6090 : 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 292440 : isolate->factory()->NewConstantElementsPair(kind, elements);
783 :
784 292440 : constant_elements_ = literals;
785 : }
786 :
787 444579 : bool ArrayLiteral::IsFastCloningSupported() const {
788 444579 : return depth() <= 1 &&
789 219493 : values()->length() <=
790 225086 : 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 308441 : void ArrayLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
799 : LanguageMode language_mode,
800 11313868 : 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 22627736 : for (int array_index = 0; array_index < values()->length(); array_index++) {
806 11087540 : Expression* subexpr = values()->at(array_index);
807 : DCHECK(!subexpr->IsSpread());
808 11087540 : 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 82113 : literal_slot_ = spec->AddKeyedStoreICSlot(language_mode);
813 390554 : return;
814 : }
815 : }
816 :
817 :
818 14040687 : Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
819 : Isolate* isolate) {
820 14040688 : if (expression->IsLiteral()) {
821 25657322 : return expression->AsLiteral()->value();
822 : }
823 1212027 : if (CompileTimeValue::IsCompileTimeValue(expression)) {
824 293169 : return CompileTimeValue::GetValue(isolate, expression);
825 : }
826 918860 : return isolate->factory()->uninitialized_value();
827 : }
828 :
829 350405 : void MaterializedLiteral::InitDepthAndFlags() {
830 350405 : if (IsArrayLiteral()) {
831 145558 : return AsArrayLiteral()->InitDepthAndFlags();
832 : }
833 277626 : if (IsObjectLiteral()) {
834 543726 : return AsObjectLiteral()->InitDepthAndFlags();
835 : }
836 : DCHECK(IsRegExpLiteral());
837 : DCHECK_LE(1, depth()); // Depth should be initialized.
838 : }
839 :
840 345952 : void MaterializedLiteral::BuildConstants(Isolate* isolate) {
841 345952 : if (IsArrayLiteral()) {
842 142928 : return AsArrayLiteral()->BuildConstantElements(isolate);
843 : }
844 274488 : if (IsObjectLiteral()) {
845 537496 : return AsObjectLiteral()->BuildConstantProperties(isolate);
846 : }
847 : DCHECK(IsRegExpLiteral());
848 : }
849 :
850 :
851 185691 : 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 185691 : set_to_boolean_types(oracle->ToBooleanTypes(expression()->test_id()));
858 185691 : }
859 :
860 :
861 149208 : 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 149208 : set_to_boolean_types(oracle->ToBooleanTypes(right()->test_id()));
868 149208 : }
869 :
870 3752718 : void BinaryOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
871 : LanguageMode language_mode,
872 3752718 : FeedbackSlotCache* cache) {
873 : // Feedback vector slot is only used by interpreter for binary operations.
874 : // Full-codegen uses AstId to record type feedback.
875 3752718 : 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 2777647 : feedback_slot_ = spec->AddInterpreterBinaryOpICSlot();
883 2777647 : return;
884 : }
885 : }
886 :
887 : static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
888 : // Add is not commutative due to potential for string addition.
889 638468 : 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 1013713 : static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
895 : Expression** expr, Smi** literal) {
896 1013713 : if (right->IsSmiLiteral()) {
897 307054 : *expr = left;
898 614108 : *literal = right->AsLiteral()->AsSmiLiteral();
899 307054 : return true;
900 : }
901 : return false;
902 : }
903 :
904 930259 : bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
905 638468 : Smi** literal) {
906 1568727 : return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
907 83454 : (IsCommutativeOperationWithSmiLiteral(op()) &&
908 1013713 : MatchSmiLiteralOperation(right_, left_, subexpr, literal));
909 : }
910 :
911 4286825 : static bool IsTypeof(Expression* expr) {
912 4774009 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
913 4774009 : return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
914 : }
915 :
916 2299045 : void CompareOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
917 : LanguageMode language_mode,
918 2299045 : FeedbackSlotCache* cache_) {
919 : // Feedback vector slot is only used by interpreter for binary operations.
920 : // Full-codegen uses AstId to record type feedback.
921 2299045 : switch (op()) {
922 : // instanceof and in do not collect type feedback.
923 : case Token::INSTANCEOF:
924 : case Token::IN:
925 2299045 : return;
926 : default:
927 2257700 : feedback_slot_ = spec->AddInterpreterCompareICSlot();
928 : }
929 : }
930 :
931 : // Check for the pattern: typeof <expression> equals <string literal>.
932 4286825 : static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
933 : Expression* right, Expression** expr,
934 : Literal** literal) {
935 4572320 : if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
936 570990 : *expr = left->AsUnaryOperation()->expression();
937 570990 : *literal = right->AsLiteral();
938 285495 : return true;
939 : }
940 : return false;
941 : }
942 :
943 2286108 : bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
944 4286825 : Literal** literal) {
945 6572933 : return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
946 6287542 : MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
947 : }
948 :
949 :
950 3999385 : static bool IsVoidOfLiteral(Expression* expr) {
951 4312956 : UnaryOperation* maybe_unary = expr->AsUnaryOperation();
952 201034 : return maybe_unary != NULL &&
953 4111922 : maybe_unary->op() == Token::VOID &&
954 3999385 : maybe_unary->expression()->IsLiteral();
955 : }
956 :
957 :
958 : // Check for the pattern: void <literal> equals <expression> or
959 : // undefined equals <expression>
960 3999385 : static bool MatchLiteralCompareUndefined(Expression* left,
961 : Token::Value op,
962 : Expression* right,
963 : Expression** expr) {
964 4111914 : if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
965 111141 : *expr = right;
966 111141 : return true;
967 : }
968 3935478 : if (left->IsUndefinedLiteral() && Token::IsEqualityOp(op)) {
969 47162 : *expr = right;
970 47162 : return true;
971 : }
972 : return false;
973 : }
974 :
975 5999998 : bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
976 5999998 : return MatchLiteralCompareUndefined(left_, op(), right_, expr) ||
977 5998157 : MatchLiteralCompareUndefined(right_, op(), left_, expr);
978 : }
979 :
980 :
981 : // Check for the pattern: null equals <expression>
982 3683430 : static bool MatchLiteralCompareNull(Expression* left,
983 : Token::Value op,
984 : Expression* right,
985 : Expression** expr) {
986 3788183 : if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
987 103304 : *expr = right;
988 103304 : return true;
989 : }
990 : return false;
991 : }
992 :
993 :
994 5525740 : bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
995 5525740 : return MatchLiteralCompareNull(left_, op(), right_, expr) ||
996 5524550 : 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 1353085 : void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
1007 1353085 : if (IsUnaryOperation()) {
1008 371382 : AsUnaryOperation()->RecordToBooleanTypeFeedback(oracle);
1009 1167394 : } else if (IsBinaryOperation()) {
1010 298416 : AsBinaryOperation()->RecordToBooleanTypeFeedback(oracle);
1011 : } else {
1012 1018186 : set_to_boolean_types(oracle->ToBooleanTypes(test_id()));
1013 : }
1014 1353085 : }
1015 :
1016 800964 : SmallMapList* Expression::GetReceiverTypes() {
1017 1601928 : 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 71612 : NODE_LIST(GENERATE_CASE)
1025 : #undef NODE_LIST
1026 : #undef GENERATE_CASE
1027 : default:
1028 0 : UNREACHABLE();
1029 : return nullptr;
1030 : }
1031 : }
1032 :
1033 24539 : KeyedAccessStoreMode Expression::GetStoreMode() const {
1034 49078 : switch (node_type()) {
1035 : #define GENERATE_CASE(Node) \
1036 : case k##Node: \
1037 : return static_cast<const Node*>(this)->GetStoreMode();
1038 5251 : PROPERTY_NODE_LIST(GENERATE_CASE)
1039 : #undef GENERATE_CASE
1040 : default:
1041 0 : UNREACHABLE();
1042 : return STANDARD_STORE;
1043 : }
1044 : }
1045 :
1046 107042 : IcCheckType Expression::GetKeyType() const {
1047 214084 : switch (node_type()) {
1048 : #define GENERATE_CASE(Node) \
1049 : case k##Node: \
1050 : return static_cast<const Node*>(this)->GetKeyType();
1051 107042 : PROPERTY_NODE_LIST(GENERATE_CASE)
1052 : #undef GENERATE_CASE
1053 : default:
1054 0 : UNREACHABLE();
1055 : return PROPERTY;
1056 : }
1057 : }
1058 :
1059 800964 : bool Expression::IsMonomorphic() const {
1060 1601928 : switch (node_type()) {
1061 : #define GENERATE_CASE(Node) \
1062 : case k##Node: \
1063 : return static_cast<const Node*>(this)->IsMonomorphic();
1064 593297 : PROPERTY_NODE_LIST(GENERATE_CASE)
1065 207667 : CALL_NODE_LIST(GENERATE_CASE)
1066 : #undef GENERATE_CASE
1067 : default:
1068 0 : UNREACHABLE();
1069 : return false;
1070 : }
1071 : }
1072 :
1073 4166613 : void Call::AssignFeedbackSlots(FeedbackVectorSpec* spec,
1074 : LanguageMode language_mode,
1075 : FeedbackSlotCache* cache) {
1076 4166617 : ic_slot_ = spec->AddCallICSlot();
1077 4166617 : }
1078 :
1079 8282930 : Call::CallType Call::GetCallType() const {
1080 5544249 : VariableProxy* proxy = expression()->AsVariableProxy();
1081 3571458 : if (proxy != NULL) {
1082 1972798 : if (proxy->var()->IsUnallocated()) {
1083 : return GLOBAL_CALL;
1084 994469 : } else if (proxy->var()->IsLookupSlot()) {
1085 : // Calls going through 'with' always use DYNAMIC rather than DYNAMIC_LOCAL
1086 : // or DYNAMIC_GLOBAL.
1087 235343 : return proxy->var()->mode() == DYNAMIC ? WITH_CALL : OTHER_CALL;
1088 : }
1089 : }
1090 :
1091 4715568 : if (expression()->IsSuperCallReference()) return SUPER_CALL;
1092 :
1093 3818852 : Property* property = expression()->AsProperty();
1094 2353694 : if (property != nullptr) {
1095 1465157 : bool is_super = property->IsSuperAccess();
1096 1465159 : if (property->key()->IsPropertyName()) {
1097 1455994 : 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 534761 : CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements,
1107 : int pos)
1108 : : Expression(pos, kCaseClause),
1109 : label_(label),
1110 : statements_(statements),
1111 1604283 : compare_type_(AstType::None()) {}
1112 :
1113 243037 : void CaseClause::AssignFeedbackSlots(FeedbackVectorSpec* spec,
1114 : LanguageMode language_mode,
1115 : FeedbackSlotCache* cache) {
1116 243037 : feedback_slot_ = spec->AddInterpreterCompareICSlot();
1117 243037 : }
1118 :
1119 2530861 : uint32_t Literal::Hash() {
1120 2530861 : return raw_value()->IsString()
1121 2514770 : ? raw_value()->AsString()->hash()
1122 5077813 : : ComputeLongHash(double_to_uint64(raw_value()->AsNumber()));
1123 : }
1124 :
1125 :
1126 : // static
1127 99715 : bool Literal::Match(void* literal1, void* literal2) {
1128 99715 : const AstValue* x = static_cast<Literal*>(literal1)->raw_value();
1129 98987 : const AstValue* y = static_cast<Literal*>(literal2)->raw_value();
1130 298417 : 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
|