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/crankshaft/hydrogen-instructions.h"
6 :
7 : #include "src/base/bits.h"
8 : #include "src/base/ieee754.h"
9 : #include "src/base/safe_math.h"
10 : #include "src/codegen.h"
11 : #include "src/crankshaft/hydrogen-infer-representation.h"
12 : #include "src/double.h"
13 : #include "src/elements.h"
14 : #include "src/factory.h"
15 : #include "src/objects-inl.h"
16 :
17 : #if V8_TARGET_ARCH_IA32
18 : #include "src/crankshaft/ia32/lithium-ia32.h" // NOLINT
19 : #elif V8_TARGET_ARCH_X64
20 : #include "src/crankshaft/x64/lithium-x64.h" // NOLINT
21 : #elif V8_TARGET_ARCH_ARM64
22 : #include "src/crankshaft/arm64/lithium-arm64.h" // NOLINT
23 : #elif V8_TARGET_ARCH_ARM
24 : #include "src/crankshaft/arm/lithium-arm.h" // NOLINT
25 : #elif V8_TARGET_ARCH_PPC
26 : #include "src/crankshaft/ppc/lithium-ppc.h" // NOLINT
27 : #elif V8_TARGET_ARCH_MIPS
28 : #include "src/crankshaft/mips/lithium-mips.h" // NOLINT
29 : #elif V8_TARGET_ARCH_MIPS64
30 : #include "src/crankshaft/mips64/lithium-mips64.h" // NOLINT
31 : #elif V8_TARGET_ARCH_S390
32 : #include "src/crankshaft/s390/lithium-s390.h" // NOLINT
33 : #elif V8_TARGET_ARCH_X87
34 : #include "src/crankshaft/x87/lithium-x87.h" // NOLINT
35 : #else
36 : #error Unsupported target architecture.
37 : #endif
38 :
39 : namespace v8 {
40 : namespace internal {
41 :
42 : #define DEFINE_COMPILE(type) \
43 : LInstruction* H##type::CompileToLithium(LChunkBuilder* builder) { \
44 : return builder->Do##type(this); \
45 : }
46 20717578 : HYDROGEN_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
47 : #undef DEFINE_COMPILE
48 :
49 4387218 : Representation RepresentationFromMachineType(MachineType type) {
50 4387218 : if (type == MachineType::Int32()) {
51 : return Representation::Integer32();
52 : }
53 :
54 3748778 : if (type == MachineType::TaggedSigned()) {
55 : return Representation::Smi();
56 : }
57 :
58 2769853 : if (type == MachineType::Pointer()) {
59 : return Representation::External();
60 : }
61 :
62 : return Representation::Tagged();
63 : }
64 :
65 160351 : Isolate* HValue::isolate() const {
66 : DCHECK(block() != NULL);
67 160351 : return block()->isolate();
68 : }
69 :
70 :
71 607 : void HValue::AssumeRepresentation(Representation r) {
72 607 : if (CheckFlag(kFlexibleRepresentation)) {
73 : ChangeRepresentation(r);
74 : // The representation of the value is dictated by type feedback and
75 : // will not be changed later.
76 : ClearFlag(kFlexibleRepresentation);
77 : }
78 607 : }
79 :
80 :
81 114774 : void HValue::InferRepresentation(HInferRepresentationPhase* h_infer) {
82 : DCHECK(CheckFlag(kFlexibleRepresentation));
83 114774 : Representation new_rep = RepresentationFromInputs();
84 114774 : UpdateRepresentation(new_rep, h_infer, "inputs");
85 114774 : new_rep = RepresentationFromUses();
86 114774 : UpdateRepresentation(new_rep, h_infer, "uses");
87 114774 : if (representation().IsSmi() && HasNonSmiUse()) {
88 : UpdateRepresentation(
89 43549 : Representation::Integer32(), h_infer, "use requirements");
90 : }
91 114774 : }
92 :
93 :
94 998853 : Representation HValue::RepresentationFromUses() {
95 998853 : if (HasNoUses()) return Representation::None();
96 966091 : Representation result = Representation::None();
97 :
98 2089865 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
99 2089865 : HValue* use = it.value();
100 2089865 : Representation rep = use->observed_input_representation(it.index());
101 2089863 : result = result.generalize(rep);
102 :
103 2089865 : if (FLAG_trace_representation) {
104 : PrintF("#%d %s is used by #%d %s as %s%s\n",
105 : id(), Mnemonic(), use->id(), use->Mnemonic(), rep.Mnemonic(),
106 0 : (use->CheckFlag(kTruncatingToInt32) ? "-trunc" : ""));
107 : }
108 : }
109 966094 : if (IsPhi()) {
110 : result = result.generalize(
111 445427 : HPhi::cast(this)->representation_from_indirect_uses());
112 : }
113 :
114 : // External representations are dealt with separately.
115 966091 : return result.IsExternal() ? Representation::None() : result;
116 : }
117 :
118 :
119 3795996 : void HValue::UpdateRepresentation(Representation new_rep,
120 : HInferRepresentationPhase* h_infer,
121 1079684 : const char* reason) {
122 3795996 : Representation r = representation();
123 3795996 : if (new_rep.is_more_general_than(r)) {
124 1177072 : if (CheckFlag(kCannotBeTagged) && new_rep.IsTagged()) return;
125 1077724 : if (FLAG_trace_representation) {
126 : PrintF("Changing #%d %s representation %s -> %s based on %s\n",
127 0 : id(), Mnemonic(), r.Mnemonic(), new_rep.Mnemonic(), reason);
128 : }
129 : ChangeRepresentation(new_rep);
130 1077725 : AddDependantsToWorklist(h_infer);
131 : }
132 : }
133 :
134 :
135 1077726 : void HValue::AddDependantsToWorklist(HInferRepresentationPhase* h_infer) {
136 2512320 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
137 2512316 : h_infer->AddToWorklist(it.value());
138 : }
139 3915172 : for (int i = 0; i < OperandCount(); ++i) {
140 2837456 : h_infer->AddToWorklist(OperandAt(i));
141 : }
142 1077720 : }
143 :
144 :
145 : static int32_t ConvertAndSetOverflow(Representation r,
146 : int64_t result,
147 : bool* overflow) {
148 384638 : if (r.IsSmi()) {
149 3104 : if (result > Smi::kMaxValue) {
150 : *overflow = true;
151 : return Smi::kMaxValue;
152 : }
153 1552 : if (result < Smi::kMinValue) {
154 : *overflow = true;
155 : return Smi::kMinValue;
156 : }
157 : } else {
158 680090 : if (result > kMaxInt) {
159 : *overflow = true;
160 : return kMaxInt;
161 : }
162 501080 : if (result < kMinInt) {
163 : *overflow = true;
164 : return kMinInt;
165 : }
166 : }
167 402546 : return static_cast<int32_t>(result);
168 : }
169 :
170 :
171 : static int32_t AddWithoutOverflow(Representation r,
172 : int32_t a,
173 : int32_t b,
174 : bool* overflow) {
175 624906 : int64_t result = static_cast<int64_t>(a) + static_cast<int64_t>(b);
176 : return ConvertAndSetOverflow(r, result, overflow);
177 : }
178 :
179 :
180 : static int32_t SubWithoutOverflow(Representation r,
181 : int32_t a,
182 : int32_t b,
183 : bool* overflow) {
184 27728 : int64_t result = static_cast<int64_t>(a) - static_cast<int64_t>(b);
185 : return ConvertAndSetOverflow(r, result, overflow);
186 : }
187 :
188 :
189 : static int32_t MulWithoutOverflow(const Representation& r,
190 : int32_t a,
191 : int32_t b,
192 : bool* overflow) {
193 30560 : int64_t result = static_cast<int64_t>(a) * static_cast<int64_t>(b);
194 : return ConvertAndSetOverflow(r, result, overflow);
195 : }
196 :
197 :
198 0 : int32_t Range::Mask() const {
199 149440 : if (lower_ == upper_) return lower_;
200 94426 : if (lower_ >= 0) {
201 : int32_t res = 1;
202 556030 : while (res < upper_) {
203 497358 : res = (res << 1) | 1;
204 : }
205 : return res;
206 : }
207 : return 0xffffffff;
208 : }
209 :
210 :
211 149278 : void Range::AddConstant(int32_t value) {
212 298556 : if (value == 0) return;
213 : bool may_overflow = false; // Overflow is ignored here.
214 : Representation r = Representation::Integer32();
215 298556 : lower_ = AddWithoutOverflow(r, lower_, value, &may_overflow);
216 298556 : upper_ = AddWithoutOverflow(r, upper_, value, &may_overflow);
217 : #ifdef DEBUG
218 : Verify();
219 : #endif
220 : }
221 :
222 :
223 473153 : void Range::Intersect(Range* other) {
224 946306 : upper_ = Min(upper_, other->upper_);
225 946306 : lower_ = Max(lower_, other->lower_);
226 473159 : bool b = CanBeMinusZero() && other->CanBeMinusZero();
227 : set_can_be_minus_zero(b);
228 473153 : }
229 :
230 :
231 19017 : void Range::Union(Range* other) {
232 38034 : upper_ = Max(upper_, other->upper_);
233 38034 : lower_ = Min(lower_, other->lower_);
234 34263 : bool b = CanBeMinusZero() || other->CanBeMinusZero();
235 : set_can_be_minus_zero(b);
236 19017 : }
237 :
238 :
239 115 : void Range::CombinedMax(Range* other) {
240 230 : upper_ = Max(upper_, other->upper_);
241 230 : lower_ = Max(lower_, other->lower_);
242 190 : set_can_be_minus_zero(CanBeMinusZero() || other->CanBeMinusZero());
243 115 : }
244 :
245 :
246 98 : void Range::CombinedMin(Range* other) {
247 196 : upper_ = Min(upper_, other->upper_);
248 196 : lower_ = Min(lower_, other->lower_);
249 172 : set_can_be_minus_zero(CanBeMinusZero() || other->CanBeMinusZero());
250 98 : }
251 :
252 :
253 0 : void Range::Sar(int32_t value) {
254 13667 : int32_t bits = value & 0x1F;
255 13667 : lower_ = lower_ >> bits;
256 13667 : upper_ = upper_ >> bits;
257 : set_can_be_minus_zero(false);
258 0 : }
259 :
260 :
261 0 : void Range::Shl(int32_t value) {
262 15020 : int32_t bits = value & 0x1F;
263 15020 : int old_lower = lower_;
264 15020 : int old_upper = upper_;
265 15020 : lower_ = lower_ << bits;
266 15020 : upper_ = upper_ << bits;
267 15020 : if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
268 10724 : upper_ = kMaxInt;
269 10724 : lower_ = kMinInt;
270 : }
271 : set_can_be_minus_zero(false);
272 0 : }
273 :
274 :
275 326350 : bool Range::AddAndCheckOverflow(const Representation& r, Range* other) {
276 : bool may_overflow = false;
277 326350 : lower_ = AddWithoutOverflow(r, lower_, other->lower(), &may_overflow);
278 326350 : upper_ = AddWithoutOverflow(r, upper_, other->upper(), &may_overflow);
279 163175 : if (may_overflow) {
280 : Clear();
281 : } else {
282 : KeepOrder();
283 : }
284 : #ifdef DEBUG
285 : Verify();
286 : #endif
287 163175 : return may_overflow;
288 : }
289 :
290 :
291 27728 : bool Range::SubAndCheckOverflow(const Representation& r, Range* other) {
292 : bool may_overflow = false;
293 27728 : lower_ = SubWithoutOverflow(r, lower_, other->upper(), &may_overflow);
294 27728 : upper_ = SubWithoutOverflow(r, upper_, other->lower(), &may_overflow);
295 13864 : if (may_overflow) {
296 : Clear();
297 : } else {
298 : KeepOrder();
299 : }
300 : #ifdef DEBUG
301 : Verify();
302 : #endif
303 13864 : return may_overflow;
304 : }
305 :
306 0 : void Range::Clear() {
307 105054 : lower_ = kMinInt;
308 105054 : upper_ = kMaxInt;
309 0 : }
310 :
311 0 : void Range::KeepOrder() {
312 79216 : if (lower_ > upper_) {
313 : int32_t tmp = lower_;
314 0 : lower_ = upper_;
315 0 : upper_ = tmp;
316 : }
317 0 : }
318 :
319 :
320 : #ifdef DEBUG
321 : void Range::Verify() const {
322 : DCHECK(lower_ <= upper_);
323 : }
324 : #endif
325 :
326 :
327 15280 : bool Range::MulAndCheckOverflow(const Representation& r, Range* other) {
328 : bool may_overflow = false;
329 7640 : int v1 = MulWithoutOverflow(r, lower_, other->lower(), &may_overflow);
330 : int v2 = MulWithoutOverflow(r, lower_, other->upper(), &may_overflow);
331 7640 : int v3 = MulWithoutOverflow(r, upper_, other->lower(), &may_overflow);
332 : int v4 = MulWithoutOverflow(r, upper_, other->upper(), &may_overflow);
333 7640 : if (may_overflow) {
334 : Clear();
335 : } else {
336 409 : lower_ = Min(Min(v1, v2), Min(v3, v4));
337 409 : upper_ = Max(Max(v1, v2), Max(v3, v4));
338 : }
339 : #ifdef DEBUG
340 : Verify();
341 : #endif
342 7640 : return may_overflow;
343 : }
344 :
345 :
346 2747328 : bool HValue::IsDefinedAfter(HBasicBlock* other) const {
347 2747328 : return block()->block_id() > other->block_id();
348 : }
349 :
350 :
351 200252 : HUseListNode* HUseListNode::tail() {
352 : // Skip and remove dead items in the use list.
353 105929658 : while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) {
354 29052457 : tail_ = tail_->tail_;
355 : }
356 200252 : return tail_;
357 : }
358 :
359 :
360 341370 : bool HValue::CheckUsesForFlag(Flag f) const {
361 34778 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
362 654278 : if (it.value()->IsSimulate()) continue;
363 636510 : if (!it.value()->CheckFlag(f)) return false;
364 : }
365 49009 : return true;
366 : }
367 :
368 :
369 328587 : bool HValue::CheckUsesForFlag(Flag f, HValue** value) const {
370 291367 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
371 1013142 : if (it.value()->IsSimulate()) continue;
372 965270 : if (!it.value()->CheckFlag(f)) {
373 215204 : *value = it.value();
374 215204 : return false;
375 : }
376 : }
377 113383 : return true;
378 : }
379 :
380 :
381 251236 : bool HValue::HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const {
382 : bool return_value = false;
383 32821 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
384 512824 : if (it.value()->IsSimulate()) continue;
385 509540 : if (!it.value()->CheckFlag(f)) return false;
386 : return_value = true;
387 : }
388 27645 : return return_value;
389 : }
390 :
391 :
392 17309204 : HUseIterator::HUseIterator(HUseListNode* head) : next_(head) {
393 17309204 : Advance();
394 13247792 : }
395 :
396 :
397 52684608 : void HUseIterator::Advance() {
398 52684608 : current_ = next_;
399 125200388 : if (current_ != NULL) {
400 36257890 : next_ = current_->tail();
401 36257890 : value_ = current_->value();
402 36257890 : index_ = current_->index();
403 : }
404 52684608 : }
405 :
406 :
407 170632 : int HValue::UseCount() const {
408 : int count = 0;
409 1158581 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count;
410 170632 : return count;
411 : }
412 :
413 :
414 3468474 : HUseListNode* HValue::RemoveUse(HValue* value, int index) {
415 : HUseListNode* previous = NULL;
416 13352942 : HUseListNode* current = use_list_;
417 9849246 : while (current != NULL) {
418 9884468 : if (current->value() == value && current->index() == index) {
419 3468460 : if (previous == NULL) {
420 2808392 : use_list_ = current->tail();
421 : } else {
422 : previous->set_tail(current->tail());
423 : }
424 : break;
425 : }
426 :
427 : previous = current;
428 : current = current->tail();
429 : }
430 :
431 : #ifdef DEBUG
432 : // Do not reuse use list nodes in debug mode, zap them.
433 : if (current != NULL) {
434 : HUseListNode* temp =
435 : new(block()->zone())
436 : HUseListNode(current->value(), current->index(), NULL);
437 : current->Zap();
438 : current = temp;
439 : }
440 : #endif
441 3468474 : return current;
442 : }
443 :
444 :
445 22303089 : bool HValue::Equals(HValue* other) {
446 15857814 : if (other->opcode() != opcode()) return false;
447 12943534 : if (!other->representation().Equals(representation())) return false;
448 10417329 : if (!other->type_.Equals(type_)) return false;
449 6445275 : if (other->flags() != flags()) return false;
450 6289610 : if (OperandCount() != other->OperandCount()) return false;
451 805026 : for (int i = 0; i < OperandCount(); ++i) {
452 828497 : if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false;
453 : }
454 6266135 : bool result = DataEquals(other);
455 : DCHECK(!result || Hashcode() == other->Hashcode());
456 6266134 : return result;
457 : }
458 :
459 :
460 8573482 : intptr_t HValue::Hashcode() {
461 8573482 : intptr_t result = opcode();
462 8573494 : int count = OperandCount();
463 21786165 : for (int i = 0; i < count; ++i) {
464 13212759 : result = result * 19 + OperandAt(i)->id() + (result >> 7);
465 : }
466 8573406 : return result;
467 : }
468 :
469 :
470 10451073 : const char* HValue::Mnemonic() const {
471 10451073 : switch (opcode()) {
472 : #define MAKE_CASE(type) case k##type: return #type;
473 : HYDROGEN_CONCRETE_INSTRUCTION_LIST(MAKE_CASE)
474 : #undef MAKE_CASE
475 : case kPhi: return "Phi";
476 : default: return "";
477 : }
478 : }
479 :
480 :
481 48844346 : bool HValue::CanReplaceWithDummyUses() {
482 48844346 : return FLAG_unreachable_code_elimination &&
483 4013980 : !(block()->IsReachable() ||
484 2932739 : IsBlockEntry() ||
485 4784196 : IsControlInstruction() ||
486 1846023 : IsArgumentsObject() ||
487 1842814 : IsCapturedObject() ||
488 865802 : IsSimulate() ||
489 : IsEnterInlined() ||
490 860388 : IsLeaveInlined());
491 : }
492 :
493 :
494 30939 : bool HValue::IsInteger32Constant() {
495 1414902 : return IsConstant() && HConstant::cast(this)->HasInteger32Value();
496 : }
497 :
498 :
499 29507 : int32_t HValue::GetInteger32Constant() {
500 377978 : return HConstant::cast(this)->Integer32Value();
501 : }
502 :
503 :
504 962821 : bool HValue::EqualsInteger32Constant(int32_t value) {
505 1305634 : return IsInteger32Constant() && GetInteger32Constant() == value;
506 : }
507 :
508 :
509 27674147 : void HValue::SetOperandAt(int index, HValue* value) {
510 27674147 : RegisterUse(index, value);
511 27674006 : InternalSetOperandAt(index, value);
512 27674068 : }
513 :
514 :
515 6726132 : void HValue::DeleteAndReplaceWith(HValue* other) {
516 : // We replace all uses first, so Delete can assert that there are none.
517 6726132 : if (other != NULL) ReplaceAllUsesWith(other);
518 6726134 : Kill();
519 6726124 : DeleteFromGraph();
520 6726119 : }
521 :
522 :
523 4049466 : void HValue::ReplaceAllUsesWith(HValue* other) {
524 13499338 : while (use_list_ != NULL) {
525 10800820 : HUseListNode* list_node = use_list_;
526 : HValue* value = list_node->value();
527 : DCHECK(!value->block()->IsStartBlock());
528 10800820 : value->InternalSetOperandAt(list_node->index(), other);
529 5400406 : use_list_ = list_node->tail();
530 5400406 : list_node->set_tail(other->use_list_);
531 5400406 : other->use_list_ = list_node;
532 : }
533 4049462 : }
534 :
535 :
536 7105171 : void HValue::Kill() {
537 : // Instead of going through the entire use list of each operand, we only
538 : // check the first item in each use list and rely on the tail() method to
539 : // skip dead items, removing them lazily next time we traverse the list.
540 : SetFlag(kIsDead);
541 10782861 : for (int i = 0; i < OperandCount(); ++i) {
542 3677687 : HValue* operand = OperandAt(i);
543 3677690 : if (operand == NULL) continue;
544 4707189 : HUseListNode* first = operand->use_list_;
545 7012320 : if (first != NULL && first->value()->CheckFlag(kIsDead)) {
546 576838 : operand->use_list_ = first->tail();
547 : }
548 : }
549 7105163 : }
550 :
551 :
552 67715526 : void HValue::SetBlock(HBasicBlock* block) {
553 : DCHECK(block_ == NULL || block == NULL);
554 34529321 : block_ = block;
555 34529321 : if (id_ == kNoNumber && block != NULL) {
556 33186153 : id_ = block->graph()->GetNextValueID(this);
557 : }
558 34529269 : }
559 :
560 :
561 0 : std::ostream& operator<<(std::ostream& os, const HValue& v) {
562 0 : return v.PrintTo(os);
563 : }
564 :
565 :
566 0 : std::ostream& operator<<(std::ostream& os, const TypeOf& t) {
567 0 : if (t.value->representation().IsTagged() &&
568 : !t.value->type().Equals(HType::Tagged()))
569 : return os;
570 0 : return os << " type:" << t.value->type();
571 : }
572 :
573 :
574 0 : std::ostream& operator<<(std::ostream& os, const ChangesOf& c) {
575 0 : GVNFlagSet changes_flags = c.value->ChangesFlags();
576 0 : if (changes_flags.IsEmpty()) return os;
577 0 : os << " changes[";
578 0 : if (changes_flags == c.value->AllSideEffectsFlagSet()) {
579 0 : os << "*";
580 : } else {
581 : bool add_comma = false;
582 : #define PRINT_DO(Type) \
583 : if (changes_flags.Contains(k##Type)) { \
584 : if (add_comma) os << ","; \
585 : add_comma = true; \
586 : os << #Type; \
587 : }
588 0 : GVN_TRACKED_FLAG_LIST(PRINT_DO);
589 0 : GVN_UNTRACKED_FLAG_LIST(PRINT_DO);
590 : #undef PRINT_DO
591 : }
592 0 : return os << "]";
593 : }
594 :
595 :
596 805234 : bool HValue::HasMonomorphicJSObjectType() {
597 1610468 : return !GetMonomorphicJSObjectMap().is_null();
598 : }
599 :
600 :
601 29475715 : bool HValue::UpdateInferredType() {
602 29475715 : HType type = CalculateInferredType();
603 29475759 : bool result = (!type.Equals(type_));
604 29475759 : type_ = type;
605 29475759 : return result;
606 : }
607 :
608 :
609 51839311 : void HValue::RegisterUse(int index, HValue* new_value) {
610 27674152 : HValue* old_value = OperandAt(index);
611 55348712 : if (old_value == new_value) return;
612 :
613 : HUseListNode* removed = NULL;
614 27633063 : if (old_value != NULL) {
615 3468475 : removed = old_value->RemoveUse(this, index);
616 : }
617 :
618 27633629 : if (new_value != NULL) {
619 27633629 : if (removed == NULL) {
620 24165159 : new_value->use_list_ = new(new_value->block()->zone()) HUseListNode(
621 48330202 : this, index, new_value->use_list_);
622 : } else {
623 3468470 : removed->set_tail(new_value->use_list_);
624 3468470 : new_value->use_list_ = removed;
625 : }
626 : }
627 : }
628 :
629 :
630 877718 : void HValue::AddNewRange(Range* r, Zone* zone) {
631 438859 : if (!HasRange()) ComputeInitialRange(zone);
632 438859 : if (!HasRange()) range_ = new(zone) Range();
633 : DCHECK(HasRange());
634 438859 : r->StackUpon(range_);
635 438859 : range_ = r;
636 438859 : }
637 :
638 :
639 418101 : void HValue::RemoveLastAddedRange() {
640 : DCHECK(HasRange());
641 : DCHECK(range_->next() != NULL);
642 418101 : range_ = range_->next();
643 418101 : }
644 :
645 :
646 10450933 : void HValue::ComputeInitialRange(Zone* zone) {
647 : DCHECK(!HasRange());
648 10450933 : range_ = InferRange(zone);
649 : DCHECK(HasRange());
650 10451127 : }
651 :
652 :
653 0 : std::ostream& HInstruction::PrintTo(std::ostream& os) const { // NOLINT
654 0 : os << Mnemonic() << " ";
655 0 : PrintDataTo(os) << ChangesOf(this) << TypeOf(this);
656 0 : if (CheckFlag(HValue::kHasNoObservableSideEffects)) os << " [noOSE]";
657 0 : if (CheckFlag(HValue::kIsDead)) os << " [dead]";
658 0 : return os;
659 : }
660 :
661 :
662 0 : std::ostream& HInstruction::PrintDataTo(std::ostream& os) const { // NOLINT
663 0 : for (int i = 0; i < OperandCount(); ++i) {
664 0 : if (i > 0) os << " ";
665 0 : os << NameOf(OperandAt(i));
666 : }
667 0 : return os;
668 : }
669 :
670 :
671 7690492 : void HInstruction::Unlink() {
672 : DCHECK(IsLinked());
673 : DCHECK(!IsControlInstruction()); // Must never move control instructions.
674 : DCHECK(!IsBlockEntry()); // Doesn't make sense to delete these.
675 : DCHECK(previous_ != NULL);
676 7690492 : previous_->next_ = next_;
677 7690492 : if (next_ == NULL) {
678 : DCHECK(block()->last() == this);
679 37391 : block()->set_last(previous_);
680 : } else {
681 7653101 : next_->previous_ = previous_;
682 : }
683 : clear_block();
684 7690492 : }
685 :
686 :
687 2959003 : void HInstruction::InsertBefore(HInstruction* next) {
688 : DCHECK(!IsLinked());
689 : DCHECK(!next->IsBlockEntry());
690 : DCHECK(!IsControlInstruction());
691 : DCHECK(!next->block()->IsStartBlock());
692 : DCHECK(next->previous_ != NULL);
693 : HInstruction* prev = next->previous();
694 2959003 : prev->next_ = this;
695 2959003 : next->previous_ = this;
696 2959003 : next_ = next;
697 2959003 : previous_ = prev;
698 2959003 : SetBlock(next->block());
699 4958225 : if (!has_position() && next->has_position()) {
700 1559490 : set_position(next->position());
701 : }
702 2959003 : }
703 :
704 :
705 25874648 : void HInstruction::InsertAfter(HInstruction* previous) {
706 : DCHECK(!IsLinked());
707 : DCHECK(!previous->IsControlInstruction());
708 : DCHECK(!IsControlInstruction() || previous->next_ == NULL);
709 53702247 : HBasicBlock* block = previous->block();
710 : // Never insert anything except constants into the start block after finishing
711 : // it.
712 28513959 : if (block->IsStartBlock() && block->IsFinished() && !IsConstant()) {
713 : DCHECK(block->end()->SecondSuccessor() == NULL);
714 0 : InsertAfter(block->end()->FirstSuccessor()->first());
715 25874646 : return;
716 : }
717 :
718 : // If we're inserting after an instruction with side-effects that is
719 : // followed by a simulate instruction, we need to insert after the
720 : // simulate instruction instead.
721 25874647 : HInstruction* next = previous->next_;
722 25874647 : if (previous->HasObservableSideEffects() && next != NULL) {
723 : DCHECK(next->IsSimulate());
724 : previous = next;
725 0 : next = previous->next_;
726 : }
727 :
728 25874647 : previous_ = previous;
729 25874647 : next_ = next;
730 25874647 : SetBlock(block);
731 25874646 : previous->next_ = this;
732 25874646 : if (next != NULL) next->previous_ = this;
733 25874646 : if (block->last() == previous) {
734 : block->set_last(this);
735 : }
736 32446319 : if (!has_position() && previous->has_position()) {
737 12787 : set_position(previous->position());
738 : }
739 : }
740 :
741 :
742 0 : bool HInstruction::Dominates(HInstruction* other) {
743 0 : if (block() != other->block()) {
744 0 : return block()->Dominates(other->block());
745 : }
746 : // Both instructions are in the same basic block. This instruction
747 : // should precede the other one in order to dominate it.
748 0 : for (HInstruction* instr = next(); instr != NULL; instr = instr->next()) {
749 0 : if (instr == other) {
750 : return true;
751 : }
752 : }
753 : return false;
754 : }
755 :
756 :
757 : #ifdef DEBUG
758 : void HInstruction::Verify() {
759 : // Verify that input operands are defined before use.
760 : HBasicBlock* cur_block = block();
761 : for (int i = 0; i < OperandCount(); ++i) {
762 : HValue* other_operand = OperandAt(i);
763 : if (other_operand == NULL) continue;
764 : HBasicBlock* other_block = other_operand->block();
765 : if (cur_block == other_block) {
766 : if (!other_operand->IsPhi()) {
767 : HInstruction* cur = this->previous();
768 : while (cur != NULL) {
769 : if (cur == other_operand) break;
770 : cur = cur->previous();
771 : }
772 : // Must reach other operand in the same block!
773 : DCHECK(cur == other_operand);
774 : }
775 : } else {
776 : // If the following assert fires, you may have forgotten an
777 : // AddInstruction.
778 : DCHECK(other_block->Dominates(cur_block));
779 : }
780 : }
781 :
782 : // Verify that instructions that may have side-effects are followed
783 : // by a simulate instruction.
784 : if (HasObservableSideEffects() && !IsOsrEntry()) {
785 : DCHECK(next()->IsSimulate());
786 : }
787 :
788 : // Verify that instructions that can be eliminated by GVN have overridden
789 : // HValue::DataEquals. The default implementation is UNREACHABLE. We
790 : // don't actually care whether DataEquals returns true or false here.
791 : if (CheckFlag(kUseGVN)) DataEquals(this);
792 :
793 : // Verify that all uses are in the graph.
794 : for (HUseIterator use = uses(); !use.Done(); use.Advance()) {
795 : if (use.value()->IsInstruction()) {
796 : DCHECK(HInstruction::cast(use.value())->IsLinked());
797 : }
798 : }
799 : }
800 : #endif
801 :
802 :
803 166 : bool HInstruction::CanDeoptimize() {
804 166 : switch (opcode()) {
805 : case HValue::kAbnormalExit:
806 : case HValue::kAccessArgumentsAt:
807 : case HValue::kAllocate:
808 : case HValue::kArgumentsElements:
809 : case HValue::kArgumentsLength:
810 : case HValue::kArgumentsObject:
811 : case HValue::kBlockEntry:
812 : case HValue::kCallNewArray:
813 : case HValue::kCapturedObject:
814 : case HValue::kClassOfTestAndBranch:
815 : case HValue::kCompareGeneric:
816 : case HValue::kCompareHoleAndBranch:
817 : case HValue::kCompareMap:
818 : case HValue::kCompareNumericAndBranch:
819 : case HValue::kCompareObjectEqAndBranch:
820 : case HValue::kConstant:
821 : case HValue::kContext:
822 : case HValue::kDebugBreak:
823 : case HValue::kDeclareGlobals:
824 : case HValue::kDummyUse:
825 : case HValue::kEnterInlined:
826 : case HValue::kEnvironmentMarker:
827 : case HValue::kForceRepresentation:
828 : case HValue::kGoto:
829 : case HValue::kHasInstanceTypeAndBranch:
830 : case HValue::kInnerAllocatedObject:
831 : case HValue::kIsSmiAndBranch:
832 : case HValue::kIsStringAndBranch:
833 : case HValue::kIsUndetectableAndBranch:
834 : case HValue::kLeaveInlined:
835 : case HValue::kLoadFieldByIndex:
836 : case HValue::kLoadNamedField:
837 : case HValue::kLoadRoot:
838 : case HValue::kMathMinMax:
839 : case HValue::kParameter:
840 : case HValue::kPhi:
841 : case HValue::kPushArguments:
842 : case HValue::kReturn:
843 : case HValue::kSeqStringGetChar:
844 : case HValue::kStoreCodeEntry:
845 : case HValue::kStoreKeyed:
846 : case HValue::kStoreNamedField:
847 : case HValue::kStringCharCodeAt:
848 : case HValue::kStringCharFromCode:
849 : case HValue::kThisFunction:
850 : case HValue::kTypeofIsAndBranch:
851 : case HValue::kUnknownOSRValue:
852 : case HValue::kUseConst:
853 : return false;
854 :
855 : case HValue::kAdd:
856 : case HValue::kApplyArguments:
857 : case HValue::kBitwise:
858 : case HValue::kBoundsCheck:
859 : case HValue::kBranch:
860 : case HValue::kCallRuntime:
861 : case HValue::kCallWithDescriptor:
862 : case HValue::kChange:
863 : case HValue::kCheckArrayBufferNotNeutered:
864 : case HValue::kCheckHeapObject:
865 : case HValue::kCheckInstanceType:
866 : case HValue::kCheckMapValue:
867 : case HValue::kCheckMaps:
868 : case HValue::kCheckSmi:
869 : case HValue::kCheckValue:
870 : case HValue::kClampToUint8:
871 : case HValue::kDeoptimize:
872 : case HValue::kDiv:
873 : case HValue::kForInCacheArray:
874 : case HValue::kForInPrepareMap:
875 : case HValue::kHasInPrototypeChainAndBranch:
876 : case HValue::kInvokeFunction:
877 : case HValue::kLoadContextSlot:
878 : case HValue::kLoadFunctionPrototype:
879 : case HValue::kLoadKeyed:
880 : case HValue::kMathFloorOfDiv:
881 : case HValue::kMaybeGrowElements:
882 : case HValue::kMod:
883 : case HValue::kMul:
884 : case HValue::kOsrEntry:
885 : case HValue::kPower:
886 : case HValue::kPrologue:
887 : case HValue::kRor:
888 : case HValue::kSar:
889 : case HValue::kSeqStringSetChar:
890 : case HValue::kShl:
891 : case HValue::kShr:
892 : case HValue::kSimulate:
893 : case HValue::kStackCheck:
894 : case HValue::kStoreContextSlot:
895 : case HValue::kStringAdd:
896 : case HValue::kStringCompareAndBranch:
897 : case HValue::kSub:
898 : case HValue::kTransitionElementsKind:
899 : case HValue::kTrapAllocationMemento:
900 : case HValue::kTypeof:
901 : case HValue::kUnaryMathOperation:
902 : case HValue::kWrapReceiver:
903 79 : return true;
904 : }
905 0 : UNREACHABLE();
906 : return true;
907 : }
908 :
909 :
910 0 : std::ostream& operator<<(std::ostream& os, const NameOf& v) {
911 0 : return os << v.value->representation().Mnemonic() << v.value->id();
912 : }
913 :
914 0 : std::ostream& HDummyUse::PrintDataTo(std::ostream& os) const { // NOLINT
915 0 : return os << NameOf(value());
916 : }
917 :
918 :
919 0 : std::ostream& HEnvironmentMarker::PrintDataTo(
920 0 : std::ostream& os) const { // NOLINT
921 0 : return os << (kind() == BIND ? "bind" : "lookup") << " var[" << index()
922 0 : << "]";
923 : }
924 :
925 :
926 0 : std::ostream& HUnaryCall::PrintDataTo(std::ostream& os) const { // NOLINT
927 0 : return os << NameOf(value()) << " #" << argument_count();
928 : }
929 :
930 :
931 0 : std::ostream& HBinaryCall::PrintDataTo(std::ostream& os) const { // NOLINT
932 0 : return os << NameOf(first()) << " " << NameOf(second()) << " #"
933 0 : << argument_count();
934 : }
935 :
936 0 : std::ostream& HInvokeFunction::PrintTo(std::ostream& os) const { // NOLINT
937 0 : if (tail_call_mode() == TailCallMode::kAllow) os << "Tail";
938 0 : return HBinaryCall::PrintTo(os);
939 : }
940 :
941 0 : std::ostream& HInvokeFunction::PrintDataTo(std::ostream& os) const { // NOLINT
942 0 : HBinaryCall::PrintDataTo(os);
943 0 : if (syntactic_tail_call_mode() == TailCallMode::kAllow) {
944 0 : os << ", JSTailCall";
945 : }
946 0 : return os;
947 : }
948 :
949 0 : std::ostream& HBoundsCheck::PrintDataTo(std::ostream& os) const { // NOLINT
950 0 : os << NameOf(index()) << " " << NameOf(length());
951 0 : if (base() != NULL && (offset() != 0 || scale() != 0)) {
952 0 : os << " base: ((";
953 0 : if (base() != index()) {
954 0 : os << NameOf(index());
955 : } else {
956 0 : os << "index";
957 : }
958 0 : os << " + " << offset() << ") >> " << scale() << ")";
959 : }
960 0 : if (skip_check()) os << " [DISABLED]";
961 0 : return os;
962 : }
963 :
964 :
965 58568 : void HBoundsCheck::InferRepresentation(HInferRepresentationPhase* h_infer) {
966 : DCHECK(CheckFlag(kFlexibleRepresentation));
967 58568 : HValue* actual_index = index()->ActualValue();
968 58568 : HValue* actual_length = length()->ActualValue();
969 58569 : Representation index_rep = actual_index->representation();
970 : Representation length_rep = actual_length->representation();
971 67075 : if (index_rep.IsTagged() && actual_index->type().IsSmi()) {
972 0 : index_rep = Representation::Smi();
973 : }
974 58569 : if (length_rep.IsTagged() && actual_length->type().IsSmi()) {
975 : length_rep = Representation::Smi();
976 : }
977 58569 : Representation r = index_rep.generalize(length_rep);
978 58568 : if (r.is_more_general_than(Representation::Integer32())) {
979 8592 : r = Representation::Integer32();
980 : }
981 58569 : UpdateRepresentation(r, h_infer, "boundscheck");
982 58568 : }
983 :
984 :
985 68592 : Range* HBoundsCheck::InferRange(Zone* zone) {
986 : Representation r = representation();
987 68593 : if (r.IsSmiOrInteger32() && length()->HasRange()) {
988 68592 : int upper = length()->range()->upper() - (allow_equality() ? 0 : 1);
989 : int lower = 0;
990 :
991 : Range* result = new(zone) Range(lower, upper);
992 34297 : if (index()->HasRange()) {
993 34297 : result->Intersect(index()->range());
994 : }
995 :
996 : // In case of Smi representation, clamp result to Smi::kMaxValue.
997 34297 : if (r.IsSmi()) result->ClampToSmi();
998 34297 : return result;
999 : }
1000 0 : return HValue::InferRange(zone);
1001 : }
1002 :
1003 :
1004 0 : std::ostream& HCallWithDescriptor::PrintDataTo(
1005 0 : std::ostream& os) const { // NOLINT
1006 0 : for (int i = 0; i < OperandCount(); i++) {
1007 0 : os << NameOf(OperandAt(i)) << " ";
1008 : }
1009 0 : os << "#" << argument_count();
1010 0 : if (syntactic_tail_call_mode() == TailCallMode::kAllow) {
1011 0 : os << ", JSTailCall";
1012 : }
1013 0 : return os;
1014 : }
1015 :
1016 :
1017 0 : std::ostream& HCallNewArray::PrintDataTo(std::ostream& os) const { // NOLINT
1018 0 : os << ElementsKindToString(elements_kind()) << " ";
1019 0 : return HBinaryCall::PrintDataTo(os);
1020 : }
1021 :
1022 :
1023 0 : std::ostream& HCallRuntime::PrintDataTo(std::ostream& os) const { // NOLINT
1024 0 : os << function()->name << " ";
1025 0 : if (save_doubles() == kSaveFPRegs) os << "[save doubles] ";
1026 0 : return os << "#" << argument_count();
1027 : }
1028 :
1029 0 : std::ostream& HClassOfTestAndBranch::PrintDataTo(
1030 : std::ostream& os) const { // NOLINT
1031 0 : return os << "class_of_test(" << NameOf(value()) << ", \""
1032 0 : << class_name()->ToCString().get() << "\")";
1033 : }
1034 :
1035 0 : std::ostream& HWrapReceiver::PrintDataTo(std::ostream& os) const { // NOLINT
1036 0 : return os << NameOf(receiver()) << " " << NameOf(function());
1037 : }
1038 :
1039 :
1040 0 : std::ostream& HAccessArgumentsAt::PrintDataTo(
1041 : std::ostream& os) const { // NOLINT
1042 0 : return os << NameOf(arguments()) << "[" << NameOf(index()) << "], length "
1043 0 : << NameOf(length());
1044 : }
1045 :
1046 :
1047 0 : std::ostream& HControlInstruction::PrintDataTo(
1048 : std::ostream& os) const { // NOLINT
1049 0 : os << " goto (";
1050 : bool first_block = true;
1051 0 : for (HSuccessorIterator it(this); !it.Done(); it.Advance()) {
1052 0 : if (!first_block) os << ", ";
1053 0 : os << *it.Current();
1054 : first_block = false;
1055 : }
1056 0 : return os << ")";
1057 : }
1058 :
1059 :
1060 0 : std::ostream& HUnaryControlInstruction::PrintDataTo(
1061 : std::ostream& os) const { // NOLINT
1062 0 : os << NameOf(value());
1063 0 : return HControlInstruction::PrintDataTo(os);
1064 : }
1065 :
1066 :
1067 0 : std::ostream& HReturn::PrintDataTo(std::ostream& os) const { // NOLINT
1068 0 : return os << NameOf(value()) << " (pop " << NameOf(parameter_count())
1069 0 : << " values)";
1070 : }
1071 :
1072 :
1073 18077 : Representation HBranch::observed_input_representation(int index) {
1074 18077 : if (expected_input_types_ &
1075 : (ToBooleanHint::kNull | ToBooleanHint::kReceiver |
1076 : ToBooleanHint::kString | ToBooleanHint::kSymbol)) {
1077 : return Representation::Tagged();
1078 : }
1079 15007 : if (expected_input_types_ & ToBooleanHint::kUndefined) {
1080 52 : if (expected_input_types_ & ToBooleanHint::kHeapNumber) {
1081 : return Representation::Double();
1082 : }
1083 : return Representation::Tagged();
1084 : }
1085 14955 : if (expected_input_types_ & ToBooleanHint::kHeapNumber) {
1086 : return Representation::Double();
1087 : }
1088 14955 : if (expected_input_types_ & ToBooleanHint::kSmallInteger) {
1089 : return Representation::Smi();
1090 : }
1091 : return Representation::None();
1092 : }
1093 :
1094 :
1095 2827351 : bool HBranch::KnownSuccessorBlock(HBasicBlock** block) {
1096 : HValue* value = this->value();
1097 2827348 : if (value->EmitAtUses()) {
1098 : DCHECK(value->IsConstant());
1099 : DCHECK(!value->representation().IsDouble());
1100 584754 : *block = HConstant::cast(value)->BooleanValue()
1101 183478 : ? FirstSuccessor()
1102 768232 : : SecondSuccessor();
1103 584754 : return true;
1104 : }
1105 2242602 : *block = NULL;
1106 2242602 : return false;
1107 : }
1108 :
1109 :
1110 0 : std::ostream& HBranch::PrintDataTo(std::ostream& os) const { // NOLINT
1111 0 : return HUnaryControlInstruction::PrintDataTo(os) << " "
1112 0 : << expected_input_types();
1113 : }
1114 :
1115 :
1116 0 : std::ostream& HCompareMap::PrintDataTo(std::ostream& os) const { // NOLINT
1117 0 : os << NameOf(value()) << " (" << *map().handle() << ")";
1118 0 : HControlInstruction::PrintDataTo(os);
1119 0 : if (known_successor_index() == 0) {
1120 0 : os << " [true]";
1121 0 : } else if (known_successor_index() == 1) {
1122 0 : os << " [false]";
1123 : }
1124 0 : return os;
1125 : }
1126 :
1127 :
1128 0 : const char* HUnaryMathOperation::OpName() const {
1129 0 : switch (op()) {
1130 : case kMathFloor:
1131 : return "floor";
1132 : case kMathFround:
1133 0 : return "fround";
1134 : case kMathRound:
1135 0 : return "round";
1136 : case kMathAbs:
1137 0 : return "abs";
1138 : case kMathCos:
1139 0 : return "cos";
1140 : case kMathLog:
1141 0 : return "log";
1142 : case kMathExp:
1143 0 : return "exp";
1144 : case kMathSin:
1145 0 : return "sin";
1146 : case kMathSqrt:
1147 0 : return "sqrt";
1148 : case kMathPowHalf:
1149 0 : return "pow-half";
1150 : case kMathClz32:
1151 0 : return "clz32";
1152 : default:
1153 0 : UNREACHABLE();
1154 : return NULL;
1155 : }
1156 : }
1157 :
1158 :
1159 26495 : Range* HUnaryMathOperation::InferRange(Zone* zone) {
1160 : Representation r = representation();
1161 26537 : if (op() == kMathClz32) return new(zone) Range(0, 32);
1162 46022 : if (r.IsSmiOrInteger32() && value()->HasRange()) {
1163 19569 : if (op() == kMathAbs) {
1164 61 : int upper = value()->range()->upper();
1165 61 : int lower = value()->range()->lower();
1166 : bool spans_zero = value()->range()->CanBeZero();
1167 : // Math.abs(kMinInt) overflows its representation, on which the
1168 : // instruction deopts. Hence clamp it to kMaxInt.
1169 61 : int abs_upper = upper == kMinInt ? kMaxInt : abs(upper);
1170 61 : int abs_lower = lower == kMinInt ? kMaxInt : abs(lower);
1171 : Range* result =
1172 : new(zone) Range(spans_zero ? 0 : Min(abs_lower, abs_upper),
1173 61 : Max(abs_lower, abs_upper));
1174 : // In case of Smi representation, clamp Math.abs(Smi::kMinValue) to
1175 : // Smi::kMaxValue.
1176 61 : if (r.IsSmi()) result->ClampToSmi();
1177 61 : return result;
1178 : }
1179 : }
1180 26392 : return HValue::InferRange(zone);
1181 : }
1182 :
1183 :
1184 0 : std::ostream& HUnaryMathOperation::PrintDataTo(
1185 : std::ostream& os) const { // NOLINT
1186 0 : return os << OpName() << " " << NameOf(value());
1187 : }
1188 :
1189 :
1190 0 : std::ostream& HUnaryOperation::PrintDataTo(std::ostream& os) const { // NOLINT
1191 0 : return os << NameOf(value());
1192 : }
1193 :
1194 :
1195 0 : std::ostream& HHasInstanceTypeAndBranch::PrintDataTo(
1196 : std::ostream& os) const { // NOLINT
1197 0 : os << NameOf(value());
1198 0 : switch (from_) {
1199 : case FIRST_JS_RECEIVER_TYPE:
1200 0 : if (to_ == LAST_TYPE) os << " spec_object";
1201 : break;
1202 : case JS_REGEXP_TYPE:
1203 0 : if (to_ == JS_REGEXP_TYPE) os << " reg_exp";
1204 : break;
1205 : case JS_ARRAY_TYPE:
1206 0 : if (to_ == JS_ARRAY_TYPE) os << " array";
1207 : break;
1208 : case JS_FUNCTION_TYPE:
1209 0 : if (to_ == JS_FUNCTION_TYPE) os << " function";
1210 : break;
1211 : default:
1212 : break;
1213 : }
1214 0 : return os;
1215 : }
1216 :
1217 :
1218 0 : std::ostream& HTypeofIsAndBranch::PrintDataTo(
1219 : std::ostream& os) const { // NOLINT
1220 0 : os << NameOf(value()) << " == " << type_literal()->ToCString().get();
1221 0 : return HControlInstruction::PrintDataTo(os);
1222 : }
1223 :
1224 :
1225 : namespace {
1226 :
1227 0 : String* TypeOfString(HConstant* constant, Isolate* isolate) {
1228 0 : Heap* heap = isolate->heap();
1229 0 : if (constant->HasNumberValue()) return heap->number_string();
1230 0 : if (constant->HasStringValue()) return heap->string_string();
1231 0 : switch (constant->GetInstanceType()) {
1232 : case ODDBALL_TYPE: {
1233 : Unique<Object> unique = constant->GetUnique();
1234 0 : if (unique.IsKnownGlobal(heap->true_value()) ||
1235 : unique.IsKnownGlobal(heap->false_value())) {
1236 0 : return heap->boolean_string();
1237 : }
1238 0 : if (unique.IsKnownGlobal(heap->null_value())) {
1239 0 : return heap->object_string();
1240 : }
1241 : DCHECK(unique.IsKnownGlobal(heap->undefined_value()));
1242 0 : return heap->undefined_string();
1243 : }
1244 : case SYMBOL_TYPE:
1245 0 : return heap->symbol_string();
1246 : default:
1247 0 : if (constant->IsUndetectable()) return heap->undefined_string();
1248 0 : if (constant->IsCallable()) return heap->function_string();
1249 0 : return heap->object_string();
1250 : }
1251 : }
1252 :
1253 : } // namespace
1254 :
1255 :
1256 320992 : bool HTypeofIsAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
1257 321271 : if (FLAG_fold_constants && value()->IsConstant()) {
1258 : HConstant* constant = HConstant::cast(value());
1259 0 : String* type_string = TypeOfString(constant, isolate());
1260 17074 : bool same_type = type_literal_.IsKnownGlobal(type_string);
1261 0 : *block = same_type ? FirstSuccessor() : SecondSuccessor();
1262 0 : return true;
1263 320992 : } else if (value()->representation().IsSpecialization()) {
1264 : bool number_type =
1265 17074 : type_literal_.IsKnownGlobal(isolate()->heap()->number_string());
1266 17074 : *block = number_type ? FirstSuccessor() : SecondSuccessor();
1267 17074 : return true;
1268 : }
1269 303918 : *block = NULL;
1270 303918 : return false;
1271 : }
1272 :
1273 :
1274 0 : std::ostream& HCheckMapValue::PrintDataTo(std::ostream& os) const { // NOLINT
1275 0 : return os << NameOf(value()) << " " << NameOf(map());
1276 : }
1277 :
1278 :
1279 757 : HValue* HCheckMapValue::Canonicalize() {
1280 757 : if (map()->IsConstant()) {
1281 0 : HConstant* c_map = HConstant::cast(map());
1282 : return HCheckMaps::CreateAndInsertAfter(
1283 : block()->graph()->zone(), value(), c_map->MapValue(),
1284 0 : c_map->HasStableMapValue(), this);
1285 : }
1286 757 : return this;
1287 : }
1288 :
1289 :
1290 0 : std::ostream& HForInPrepareMap::PrintDataTo(std::ostream& os) const { // NOLINT
1291 0 : return os << NameOf(enumerable());
1292 : }
1293 :
1294 :
1295 0 : std::ostream& HForInCacheArray::PrintDataTo(std::ostream& os) const { // NOLINT
1296 0 : return os << NameOf(enumerable()) << " " << NameOf(map()) << "[" << idx_
1297 0 : << "]";
1298 : }
1299 :
1300 :
1301 0 : std::ostream& HLoadFieldByIndex::PrintDataTo(
1302 : std::ostream& os) const { // NOLINT
1303 0 : return os << NameOf(object()) << " " << NameOf(index());
1304 : }
1305 :
1306 :
1307 : static bool MatchLeftIsOnes(HValue* l, HValue* r, HValue** negated) {
1308 44484 : if (!l->EqualsInteger32Constant(~0)) return false;
1309 1622 : *negated = r;
1310 : return true;
1311 : }
1312 :
1313 :
1314 93804 : static bool MatchNegationViaXor(HValue* instr, HValue** negated) {
1315 93804 : if (!instr->IsBitwise()) return false;
1316 92853 : HBitwise* b = HBitwise::cast(instr);
1317 115095 : return (b->op() == Token::BIT_XOR) &&
1318 22242 : (MatchLeftIsOnes(b->left(), b->right(), negated) ||
1319 92853 : MatchLeftIsOnes(b->right(), b->left(), negated));
1320 : }
1321 :
1322 :
1323 92221 : static bool MatchDoubleNegation(HValue* instr, HValue** arg) {
1324 : HValue* negated;
1325 93804 : return MatchNegationViaXor(instr, &negated) &&
1326 93806 : MatchNegationViaXor(negated, arg);
1327 : }
1328 :
1329 :
1330 229280 : HValue* HBitwise::Canonicalize() {
1331 117186 : if (!representation().IsSmiOrInteger32()) return this;
1332 : // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
1333 112094 : int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0;
1334 112299 : if (left()->EqualsInteger32Constant(nop_constant) &&
1335 205 : !right()->CheckFlag(kUint32)) {
1336 204 : return right();
1337 : }
1338 131688 : if (right()->EqualsInteger32Constant(nop_constant) &&
1339 19799 : !left()->CheckFlag(kUint32)) {
1340 19667 : return left();
1341 : }
1342 : // Optimize double negation, a common pattern used for ToInt32(x).
1343 : HValue* arg;
1344 92260 : if (MatchDoubleNegation(this, &arg) && !arg->CheckFlag(kUint32)) {
1345 39 : return arg;
1346 : }
1347 : return this;
1348 : }
1349 :
1350 :
1351 : // static
1352 3897 : HInstruction* HAdd::New(Isolate* isolate, Zone* zone, HValue* context,
1353 : HValue* left, HValue* right,
1354 : ExternalAddType external_add_type) {
1355 : // For everything else, you should use the other factory method without
1356 : // ExternalAddType.
1357 : DCHECK_EQ(external_add_type, AddOfExternalAndTagged);
1358 3897 : return new (zone) HAdd(context, left, right, external_add_type);
1359 : }
1360 :
1361 :
1362 564241 : Representation HAdd::RepresentationFromInputs() {
1363 : Representation left_rep = left()->representation();
1364 564241 : if (left_rep.IsExternal()) {
1365 : return Representation::External();
1366 : }
1367 560224 : return HArithmeticBinaryOperation::RepresentationFromInputs();
1368 : }
1369 :
1370 :
1371 1149646 : Representation HAdd::RequiredInputRepresentation(int index) {
1372 1149646 : if (index == 2) {
1373 : Representation left_rep = left()->representation();
1374 368917 : if (left_rep.IsExternal()) {
1375 3897 : if (external_add_type_ == AddOfExternalAndTagged) {
1376 : return Representation::Tagged();
1377 : } else {
1378 : return Representation::Integer32();
1379 : }
1380 : }
1381 : }
1382 : return HArithmeticBinaryOperation::RequiredInputRepresentation(index);
1383 : }
1384 :
1385 :
1386 697311 : static bool IsIdentityOperation(HValue* arg1, HValue* arg2, int32_t identity) {
1387 1315080 : return arg1->representation().IsSpecialization() &&
1388 1315080 : arg2->EqualsInteger32Constant(identity);
1389 : }
1390 :
1391 :
1392 286187 : HValue* HAdd::Canonicalize() {
1393 : // Adding 0 is an identity operation except in case of -0: -0 + 0 = +0
1394 294063 : if (IsIdentityOperation(left(), right(), 0) &&
1395 : !left()->representation().IsDouble()) { // Left could be -0.
1396 7812 : return left();
1397 : }
1398 300638 : if (IsIdentityOperation(right(), left(), 0) &&
1399 : !left()->representation().IsDouble()) { // Right could be -0.
1400 22254 : return right();
1401 : }
1402 256121 : return this;
1403 : }
1404 :
1405 :
1406 26340 : HValue* HSub::Canonicalize() {
1407 26350 : if (IsIdentityOperation(left(), right(), 0)) return left();
1408 26330 : return this;
1409 : }
1410 :
1411 :
1412 27242 : HValue* HMul::Canonicalize() {
1413 27242 : if (IsIdentityOperation(left(), right(), 1)) return left();
1414 27242 : if (IsIdentityOperation(right(), left(), 1)) return right();
1415 27242 : return this;
1416 : }
1417 :
1418 :
1419 1361 : bool HMul::MulMinusOne() {
1420 2722 : if (left()->EqualsInteger32Constant(-1) ||
1421 1361 : right()->EqualsInteger32Constant(-1)) {
1422 : return true;
1423 : }
1424 :
1425 1302 : return false;
1426 : }
1427 :
1428 :
1429 5635 : HValue* HMod::Canonicalize() {
1430 5635 : return this;
1431 : }
1432 :
1433 :
1434 51927 : HValue* HDiv::Canonicalize() {
1435 52754 : if (IsIdentityOperation(left(), right(), 1)) return left();
1436 51100 : return this;
1437 : }
1438 :
1439 :
1440 509111 : HValue* HChange::Canonicalize() {
1441 509111 : return (from().Equals(to())) ? value() : this;
1442 : }
1443 :
1444 :
1445 4941 : HValue* HWrapReceiver::Canonicalize() {
1446 4941 : if (HasNoUses()) return NULL;
1447 4941 : if (receiver()->type().IsJSReceiver()) {
1448 : return receiver();
1449 : }
1450 4941 : return this;
1451 : }
1452 :
1453 :
1454 0 : std::ostream& HTypeof::PrintDataTo(std::ostream& os) const { // NOLINT
1455 0 : return os << NameOf(value());
1456 : }
1457 :
1458 :
1459 61533 : HInstruction* HForceRepresentation::New(Isolate* isolate, Zone* zone,
1460 : HValue* context, HValue* value,
1461 : Representation representation) {
1462 61865 : if (FLAG_fold_constants && value->IsConstant()) {
1463 : HConstant* c = HConstant::cast(value);
1464 25 : c = c->CopyToRepresentation(representation, zone);
1465 25 : if (c != NULL) return c;
1466 : }
1467 123028 : return new(zone) HForceRepresentation(value, representation);
1468 : }
1469 :
1470 :
1471 0 : std::ostream& HForceRepresentation::PrintDataTo(
1472 : std::ostream& os) const { // NOLINT
1473 0 : return os << representation().Mnemonic() << " " << NameOf(value());
1474 : }
1475 :
1476 :
1477 0 : std::ostream& HChange::PrintDataTo(std::ostream& os) const { // NOLINT
1478 : HUnaryOperation::PrintDataTo(os);
1479 0 : os << " " << from().Mnemonic() << " to " << to().Mnemonic();
1480 :
1481 0 : if (CanTruncateToSmi()) os << " truncating-smi";
1482 0 : if (CanTruncateToInt32()) os << " truncating-int32";
1483 0 : if (CanTruncateToNumber()) os << " truncating-number";
1484 0 : if (CheckFlag(kBailoutOnMinusZero)) os << " -0?";
1485 0 : return os;
1486 : }
1487 :
1488 :
1489 58505 : HValue* HUnaryMathOperation::Canonicalize() {
1490 29288 : if (op() == kMathRound || op() == kMathFloor) {
1491 : HValue* val = value();
1492 27563 : if (val->IsChange()) val = HChange::cast(val)->value();
1493 27563 : if (val->representation().IsSmiOrInteger32()) {
1494 4484 : if (val->representation().Equals(representation())) return val;
1495 0 : return Prepend(new (block()->zone())
1496 0 : HChange(val, representation(), false, false, true));
1497 : }
1498 : }
1499 76703 : if (op() == kMathFloor && representation().IsSmiOrInteger32() &&
1500 32558 : value()->IsDiv() && value()->HasOneUse()) {
1501 : HDiv* hdiv = HDiv::cast(value());
1502 :
1503 0 : HValue* left = hdiv->left();
1504 3335 : if (left->representation().IsInteger32() && !left->CheckFlag(kUint32)) {
1505 : // A value with an integer representation does not need to be transformed.
1506 6748 : } else if (left->IsChange() && HChange::cast(left)->from().IsInteger32() &&
1507 806 : !HChange::cast(left)->value()->CheckFlag(kUint32)) {
1508 : // A change from an integer32 can be replaced by the integer32 value.
1509 : left = HChange::cast(left)->value();
1510 5070 : } else if (hdiv->observed_input_representation(1).IsSmiOrInteger32()) {
1511 1813 : left = Prepend(new (block()->zone()) HChange(
1512 5439 : left, Representation::Integer32(), false, false, true));
1513 : } else {
1514 722 : return this;
1515 : }
1516 :
1517 2529 : HValue* right = hdiv->right();
1518 2613 : if (right->IsInteger32Constant()) {
1519 : right = Prepend(HConstant::cast(right)->CopyToRepresentation(
1520 5058 : Representation::Integer32(), right->block()->zone()));
1521 84 : } else if (right->representation().IsInteger32() &&
1522 : !right->CheckFlag(kUint32)) {
1523 : // A value with an integer representation does not need to be transformed.
1524 155 : } else if (right->IsChange() &&
1525 155 : HChange::cast(right)->from().IsInteger32() &&
1526 71 : !HChange::cast(right)->value()->CheckFlag(kUint32)) {
1527 : // A change from an integer32 can be replaced by the integer32 value.
1528 : right = HChange::cast(right)->value();
1529 26 : } else if (hdiv->observed_input_representation(2).IsSmiOrInteger32()) {
1530 0 : right = Prepend(new (block()->zone()) HChange(
1531 0 : right, Representation::Integer32(), false, false, true));
1532 : } else {
1533 13 : return this;
1534 : }
1535 :
1536 : return Prepend(HMathFloorOfDiv::New(
1537 7800 : block()->graph()->isolate(), block()->zone(), context(), left, right));
1538 : }
1539 25882 : return this;
1540 : }
1541 :
1542 :
1543 89306 : HValue* HCheckInstanceType::Canonicalize() {
1544 180250 : if ((check_ == IS_JS_RECEIVER && value()->type().IsJSReceiver()) ||
1545 89306 : (check_ == IS_JS_ARRAY && value()->type().IsJSArray()) ||
1546 70082 : (check_ == IS_STRING && value()->type().IsString())) {
1547 20077 : return value();
1548 : }
1549 :
1550 86815 : if (check_ == IS_INTERNALIZED_STRING && value()->IsConstant()) {
1551 4243 : if (HConstant::cast(value())->HasInternalizedStringValue()) {
1552 : return value();
1553 : }
1554 : }
1555 64986 : return this;
1556 : }
1557 :
1558 :
1559 1340 : void HCheckInstanceType::GetCheckInterval(InstanceType* first,
1560 : InstanceType* last) {
1561 : DCHECK(is_interval_check());
1562 1340 : switch (check_) {
1563 : case IS_JS_RECEIVER:
1564 1340 : *first = FIRST_JS_RECEIVER_TYPE;
1565 1340 : *last = LAST_JS_RECEIVER_TYPE;
1566 1340 : return;
1567 : case IS_JS_ARRAY:
1568 0 : *first = *last = JS_ARRAY_TYPE;
1569 0 : return;
1570 : case IS_JS_FUNCTION:
1571 0 : *first = *last = JS_FUNCTION_TYPE;
1572 0 : return;
1573 : case IS_JS_DATE:
1574 0 : *first = *last = JS_DATE_TYPE;
1575 0 : return;
1576 : default:
1577 0 : UNREACHABLE();
1578 : }
1579 : }
1580 :
1581 :
1582 48777 : void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
1583 : DCHECK(!is_interval_check());
1584 48777 : switch (check_) {
1585 : case IS_STRING:
1586 36554 : *mask = kIsNotStringMask;
1587 36554 : *tag = kStringTag;
1588 36554 : return;
1589 : case IS_INTERNALIZED_STRING:
1590 12223 : *mask = kIsNotStringMask | kIsNotInternalizedMask;
1591 12223 : *tag = kInternalizedTag;
1592 12223 : return;
1593 : default:
1594 0 : UNREACHABLE();
1595 : }
1596 : }
1597 :
1598 :
1599 0 : std::ostream& HCheckMaps::PrintDataTo(std::ostream& os) const { // NOLINT
1600 0 : os << NameOf(value()) << " [" << *maps()->at(0).handle();
1601 0 : for (int i = 1; i < maps()->size(); ++i) {
1602 0 : os << "," << *maps()->at(i).handle();
1603 : }
1604 0 : os << "]";
1605 0 : if (IsStabilityCheck()) os << "(stability-check)";
1606 0 : return os;
1607 : }
1608 :
1609 :
1610 502951 : HValue* HCheckMaps::Canonicalize() {
1611 894113 : if (!IsStabilityCheck() && maps_are_stable() && value()->IsConstant()) {
1612 : HConstant* c_value = HConstant::cast(value());
1613 184373 : if (c_value->HasObjectMap()) {
1614 368866 : for (int i = 0; i < maps()->size(); ++i) {
1615 368684 : if (c_value->ObjectMap() == maps()->at(i)) {
1616 184282 : if (maps()->size() > 1) {
1617 : set_maps(new(block()->graph()->zone()) UniqueSet<Map>(
1618 0 : maps()->at(i), block()->graph()->zone()));
1619 : }
1620 : MarkAsStabilityCheck();
1621 : break;
1622 : }
1623 : }
1624 : }
1625 : }
1626 318547 : return this;
1627 : }
1628 :
1629 :
1630 0 : std::ostream& HCheckValue::PrintDataTo(std::ostream& os) const { // NOLINT
1631 0 : return os << NameOf(value()) << " " << Brief(*object().handle());
1632 : }
1633 :
1634 :
1635 203515 : HValue* HCheckValue::Canonicalize() {
1636 164491 : return (value()->IsConstant() &&
1637 242553 : HConstant::cast(value())->EqualsUnique(object_)) ? NULL : this;
1638 : }
1639 :
1640 :
1641 0 : const char* HCheckInstanceType::GetCheckName() const {
1642 0 : switch (check_) {
1643 : case IS_JS_RECEIVER: return "object";
1644 0 : case IS_JS_ARRAY: return "array";
1645 : case IS_JS_FUNCTION:
1646 0 : return "function";
1647 : case IS_JS_DATE:
1648 0 : return "date";
1649 0 : case IS_STRING: return "string";
1650 0 : case IS_INTERNALIZED_STRING: return "internalized_string";
1651 : }
1652 0 : UNREACHABLE();
1653 : return "";
1654 : }
1655 :
1656 :
1657 0 : std::ostream& HCheckInstanceType::PrintDataTo(
1658 : std::ostream& os) const { // NOLINT
1659 0 : os << GetCheckName() << " ";
1660 0 : return HUnaryOperation::PrintDataTo(os);
1661 : }
1662 :
1663 :
1664 0 : std::ostream& HUnknownOSRValue::PrintDataTo(std::ostream& os) const { // NOLINT
1665 : const char* type = "expression";
1666 0 : if (environment_->is_local_index(index_)) type = "local";
1667 0 : if (environment_->is_special_index(index_)) type = "special";
1668 0 : if (environment_->is_parameter_index(index_)) type = "parameter";
1669 0 : return os << type << " @ " << index_;
1670 : }
1671 :
1672 :
1673 14883003 : Range* HValue::InferRange(Zone* zone) {
1674 : Range* result;
1675 15253427 : if (representation().IsSmi() || type().IsSmi()) {
1676 : result = new(zone) Range(Smi::kMinValue, Smi::kMaxValue);
1677 : result->set_can_be_minus_zero(false);
1678 : } else {
1679 : result = new(zone) Range();
1680 7253299 : result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32));
1681 : // TODO(jkummerow): The range cannot be minus zero when the upper type
1682 : // bound is Integer32.
1683 : }
1684 7629820 : return result;
1685 : }
1686 :
1687 :
1688 369991 : Range* HChange::InferRange(Zone* zone) {
1689 371188 : Range* input_range = value()->range();
1690 903660 : if (from().IsInteger32() && !value()->CheckFlag(HInstruction::kUint32) &&
1691 128015 : (to().IsSmi() ||
1692 105309 : (to().IsTagged() &&
1693 : input_range != NULL &&
1694 : input_range->IsInSmiRange()))) {
1695 152083 : set_type(HType::Smi());
1696 : ClearChangesFlag(kNewSpacePromotion);
1697 : }
1698 567109 : if (to().IsSmiOrTagged() &&
1699 : input_range != NULL &&
1700 369991 : input_range->IsInSmiRange() &&
1701 197118 : (!SmiValuesAre32Bits() ||
1702 198315 : !value()->CheckFlag(HValue::kUint32) ||
1703 : input_range->upper() != kMaxInt)) {
1704 : // The Range class can't express upper bounds in the (kMaxInt, kMaxUint32]
1705 : // interval, so we treat kMaxInt as a sentinel for this entire interval.
1706 : ClearFlag(kCanOverflow);
1707 : }
1708 : Range* result = (input_range != NULL)
1709 : ? input_range->Copy(zone)
1710 369991 : : HValue::InferRange(zone);
1711 522076 : result->set_can_be_minus_zero(!to().IsSmiOrInteger32() ||
1712 : !(CheckFlag(kAllUsesTruncatingToInt32) ||
1713 152083 : CheckFlag(kAllUsesTruncatingToSmi)));
1714 369993 : if (to().IsSmi()) result->ClampToSmi();
1715 369993 : return result;
1716 : }
1717 :
1718 :
1719 4376305 : Range* HConstant::InferRange(Zone* zone) {
1720 4376305 : if (HasInteger32Value()) {
1721 2003360 : Range* result = new(zone) Range(int32_value_, int32_value_);
1722 : result->set_can_be_minus_zero(false);
1723 2003360 : return result;
1724 : }
1725 2372952 : return HValue::InferRange(zone);
1726 : }
1727 :
1728 :
1729 0 : SourcePosition HPhi::position() const { return block()->first()->position(); }
1730 :
1731 :
1732 301146 : Range* HPhi::InferRange(Zone* zone) {
1733 49943 : Representation r = representation();
1734 301146 : if (r.IsSmiOrInteger32()) {
1735 49943 : if (block()->IsLoopHeader()) {
1736 : Range* range = r.IsSmi()
1737 : ? new(zone) Range(Smi::kMinValue, Smi::kMaxValue)
1738 34022 : : new(zone) Range(kMinInt, kMaxInt);
1739 34022 : return range;
1740 : } else {
1741 15921 : Range* range = OperandAt(0)->range()->Copy(zone);
1742 69876 : for (int i = 1; i < OperandCount(); ++i) {
1743 19017 : range->Union(OperandAt(i)->range());
1744 : }
1745 : return range;
1746 : }
1747 : } else {
1748 251203 : return HValue::InferRange(zone);
1749 : }
1750 : }
1751 :
1752 :
1753 227233 : Range* HAdd::InferRange(Zone* zone) {
1754 482868 : Representation r = representation();
1755 227233 : if (r.IsSmiOrInteger32()) {
1756 163175 : Range* a = left()->range();
1757 163175 : Range* b = right()->range();
1758 163175 : Range* res = a->Copy(zone);
1759 418810 : if (!res->AddAndCheckOverflow(r, b) ||
1760 254918 : (r.IsInteger32() && CheckFlag(kAllUsesTruncatingToInt32)) ||
1761 717 : (r.IsSmi() && CheckFlag(kAllUsesTruncatingToSmi))) {
1762 : ClearFlag(kCanOverflow);
1763 : }
1764 163175 : res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToSmi) &&
1765 149549 : !CheckFlag(kAllUsesTruncatingToInt32) &&
1766 220840 : a->CanBeMinusZero() && b->CanBeMinusZero());
1767 163175 : return res;
1768 : } else {
1769 64058 : return HValue::InferRange(zone);
1770 : }
1771 : }
1772 :
1773 :
1774 24320 : Range* HSub::InferRange(Zone* zone) {
1775 43547 : Representation r = representation();
1776 24320 : if (r.IsSmiOrInteger32()) {
1777 13864 : Range* a = left()->range();
1778 15561 : Range* b = right()->range();
1779 13864 : Range* res = a->Copy(zone);
1780 33091 : if (!res->SubAndCheckOverflow(r, b) ||
1781 18936 : (r.IsInteger32() && CheckFlag(kAllUsesTruncatingToInt32)) ||
1782 291 : (r.IsSmi() && CheckFlag(kAllUsesTruncatingToSmi))) {
1783 : ClearFlag(kCanOverflow);
1784 : }
1785 13864 : res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToSmi) &&
1786 7332 : !CheckFlag(kAllUsesTruncatingToInt32) &&
1787 15561 : a->CanBeMinusZero() && b->CanBeZero());
1788 13864 : return res;
1789 : } else {
1790 10456 : return HValue::InferRange(zone);
1791 : }
1792 : }
1793 :
1794 :
1795 23361 : Range* HMul::InferRange(Zone* zone) {
1796 38232 : Representation r = representation();
1797 23361 : if (r.IsSmiOrInteger32()) {
1798 14980 : Range* a = left()->range();
1799 17250 : Range* b = right()->range();
1800 7640 : Range* res = a->Copy(zone);
1801 22511 : if (!res->MulAndCheckOverflow(r, b) ||
1802 6959 : (((r.IsInteger32() && CheckFlag(kAllUsesTruncatingToInt32)) ||
1803 563 : (r.IsSmi() && CheckFlag(kAllUsesTruncatingToSmi))) &&
1804 291 : MulMinusOne())) {
1805 : // Truncated int multiplication is too precise and therefore not the
1806 : // same as converting to Double and back.
1807 : // Handle truncated integer multiplication by -1 special.
1808 : ClearFlag(kCanOverflow);
1809 : }
1810 7640 : res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToSmi) &&
1811 14980 : !CheckFlag(kAllUsesTruncatingToInt32) &&
1812 6871 : ((a->CanBeZero() && b->CanBeNegative()) ||
1813 2739 : (a->CanBeNegative() && b->CanBeZero())));
1814 7640 : return res;
1815 : } else {
1816 15721 : return HValue::InferRange(zone);
1817 : }
1818 : }
1819 :
1820 :
1821 49911 : Range* HDiv::InferRange(Zone* zone) {
1822 52430 : if (representation().IsInteger32()) {
1823 5038 : Range* a = left()->range();
1824 7530 : Range* b = right()->range();
1825 : Range* result = new(zone) Range();
1826 2963 : result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
1827 115 : (a->CanBeMinusZero() ||
1828 83 : (a->CanBeZero() && b->CanBeNegative())));
1829 4928 : if (!a->Includes(kMinInt) || !b->Includes(-1)) {
1830 : ClearFlag(kCanOverflow);
1831 : }
1832 :
1833 2519 : if (!b->CanBeZero()) {
1834 : ClearFlag(kCanBeDivByZero);
1835 : }
1836 2519 : return result;
1837 : } else {
1838 47392 : return HValue::InferRange(zone);
1839 : }
1840 : }
1841 :
1842 :
1843 2600 : Range* HMathFloorOfDiv::InferRange(Zone* zone) {
1844 5200 : if (representation().IsInteger32()) {
1845 13000 : Range* a = left()->range();
1846 8549 : Range* b = right()->range();
1847 : Range* result = new(zone) Range();
1848 5200 : result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
1849 773 : (a->CanBeMinusZero() ||
1850 761 : (a->CanBeZero() && b->CanBeNegative())));
1851 2600 : if (!a->Includes(kMinInt)) {
1852 : ClearFlag(kLeftCanBeMinInt);
1853 : }
1854 :
1855 2600 : if (!a->CanBeNegative()) {
1856 : ClearFlag(HValue::kLeftCanBeNegative);
1857 : }
1858 :
1859 2600 : if (!a->CanBePositive()) {
1860 : ClearFlag(HValue::kLeftCanBePositive);
1861 : }
1862 :
1863 5188 : if (!a->Includes(kMinInt) || !b->Includes(-1)) {
1864 : ClearFlag(kCanOverflow);
1865 : }
1866 :
1867 2600 : if (!b->CanBeZero()) {
1868 : ClearFlag(kCanBeDivByZero);
1869 : }
1870 2600 : return result;
1871 : } else {
1872 0 : return HValue::InferRange(zone);
1873 : }
1874 : }
1875 :
1876 :
1877 : // Returns the absolute value of its argument minus one, avoiding undefined
1878 : // behavior at kMinInt.
1879 6228 : static int32_t AbsMinus1(int32_t a) { return a < 0 ? -(a + 1) : (a - 1); }
1880 :
1881 :
1882 5408 : Range* HMod::InferRange(Zone* zone) {
1883 8522 : if (representation().IsInteger32()) {
1884 9342 : Range* a = left()->range();
1885 12302 : Range* b = right()->range();
1886 :
1887 : // The magnitude of the modulus is bounded by the right operand.
1888 : int32_t positive_bound = Max(AbsMinus1(b->lower()), AbsMinus1(b->upper()));
1889 :
1890 : // The result of the modulo operation has the sign of its left operand.
1891 3114 : bool left_can_be_negative = a->CanBeMinusZero() || a->CanBeNegative();
1892 : Range* result = new(zone) Range(left_can_be_negative ? -positive_bound : 0,
1893 6228 : a->CanBePositive() ? positive_bound : 0);
1894 :
1895 3114 : result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
1896 : left_can_be_negative);
1897 :
1898 3114 : if (!a->CanBeNegative()) {
1899 : ClearFlag(HValue::kLeftCanBeNegative);
1900 : }
1901 :
1902 6074 : if (!a->Includes(kMinInt) || !b->Includes(-1)) {
1903 : ClearFlag(HValue::kCanOverflow);
1904 : }
1905 :
1906 3114 : if (!b->CanBeZero()) {
1907 : ClearFlag(HValue::kCanBeDivByZero);
1908 : }
1909 3114 : return result;
1910 : } else {
1911 2294 : return HValue::InferRange(zone);
1912 : }
1913 : }
1914 :
1915 :
1916 1582 : Range* HMathMinMax::InferRange(Zone* zone) {
1917 1582 : if (representation().IsSmiOrInteger32()) {
1918 213 : Range* a = left()->range();
1919 213 : Range* b = right()->range();
1920 213 : Range* res = a->Copy(zone);
1921 213 : if (operation_ == kMathMax) {
1922 115 : res->CombinedMax(b);
1923 : } else {
1924 : DCHECK(operation_ == kMathMin);
1925 98 : res->CombinedMin(b);
1926 : }
1927 213 : return res;
1928 : } else {
1929 1369 : return HValue::InferRange(zone);
1930 : }
1931 : }
1932 :
1933 :
1934 1599341 : void HPushArguments::AddInput(HValue* value) {
1935 1599341 : inputs_.Add(NULL, value->block()->zone());
1936 1599341 : SetOperandAt(OperandCount() - 1, value);
1937 1599341 : }
1938 :
1939 :
1940 0 : std::ostream& HPhi::PrintTo(std::ostream& os) const { // NOLINT
1941 0 : os << "[";
1942 0 : for (int i = 0; i < OperandCount(); ++i) {
1943 0 : os << " " << NameOf(OperandAt(i)) << " ";
1944 : }
1945 0 : return os << " uses" << UseCount()
1946 0 : << representation_from_indirect_uses().Mnemonic() << " "
1947 0 : << TypeOf(this) << "]";
1948 : }
1949 :
1950 :
1951 2969794 : void HPhi::AddInput(HValue* value) {
1952 1485153 : inputs_.Add(NULL, value->block()->zone());
1953 1485153 : SetOperandAt(OperandCount() - 1, value);
1954 : // Mark phis that may have 'arguments' directly or indirectly as an operand.
1955 2969794 : if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) {
1956 : SetFlag(kIsArguments);
1957 : }
1958 1485153 : }
1959 :
1960 :
1961 0 : bool HPhi::HasRealUses() {
1962 0 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1963 0 : if (!it.value()->IsPhi()) return true;
1964 : }
1965 0 : return false;
1966 : }
1967 :
1968 :
1969 1119925 : HValue* HPhi::GetRedundantReplacement() {
1970 : HValue* candidate = NULL;
1971 : int count = OperandCount();
1972 : int position = 0;
1973 3359775 : while (position < count && candidate == NULL) {
1974 1119925 : HValue* current = OperandAt(position++);
1975 1119925 : if (current != this) candidate = current;
1976 : }
1977 1581341 : while (position < count) {
1978 1202322 : HValue* current = OperandAt(position++);
1979 1202322 : if (current != this && current != candidate) return NULL;
1980 : }
1981 : DCHECK(candidate != this);
1982 : return candidate;
1983 : }
1984 :
1985 :
1986 25 : void HPhi::DeleteFromGraph() {
1987 : DCHECK(block() != NULL);
1988 25 : block()->RemovePhi(this);
1989 : DCHECK(block() == NULL);
1990 25 : }
1991 :
1992 :
1993 316824 : void HPhi::InitRealUses(int phi_id) {
1994 : // Initialize real uses.
1995 316824 : phi_id_ = phi_id;
1996 : // Compute a conservative approximation of truncating uses before inferring
1997 : // representations. The proper, exact computation will be done later, when
1998 : // inserting representation changes.
1999 316824 : SetFlag(kTruncatingToSmi);
2000 : SetFlag(kTruncatingToInt32);
2001 958524 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
2002 2154082 : HValue* value = it.value();
2003 958524 : if (!value->IsPhi()) {
2004 693353 : Representation rep = value->observed_input_representation(it.index());
2005 : representation_from_non_phi_uses_ =
2006 693353 : representation_from_non_phi_uses().generalize(rep);
2007 693353 : if (rep.IsSmi() || rep.IsInteger32() || rep.IsDouble()) {
2008 137905 : has_type_feedback_from_uses_ = true;
2009 : }
2010 :
2011 693353 : if (FLAG_trace_representation) {
2012 : PrintF("#%d Phi is used by real #%d %s as %s\n",
2013 0 : id(), value->id(), value->Mnemonic(), rep.Mnemonic());
2014 : }
2015 693353 : if (!value->IsSimulate()) {
2016 597779 : if (!value->CheckFlag(kTruncatingToSmi)) {
2017 : ClearFlag(kTruncatingToSmi);
2018 : }
2019 597779 : if (!value->CheckFlag(kTruncatingToInt32)) {
2020 : ClearFlag(kTruncatingToInt32);
2021 : }
2022 : }
2023 : }
2024 : }
2025 316825 : }
2026 :
2027 :
2028 925097 : void HPhi::AddNonPhiUsesFrom(HPhi* other) {
2029 925097 : if (FLAG_trace_representation) {
2030 : PrintF(
2031 : "generalizing use representation '%s' of #%d Phi "
2032 : "with uses of #%d Phi '%s'\n",
2033 : representation_from_indirect_uses().Mnemonic(), id(), other->id(),
2034 0 : other->representation_from_non_phi_uses().Mnemonic());
2035 : }
2036 :
2037 : representation_from_indirect_uses_ =
2038 : representation_from_indirect_uses().generalize(
2039 925097 : other->representation_from_non_phi_uses());
2040 925097 : }
2041 :
2042 :
2043 1277270 : void HSimulate::MergeWith(ZoneList<HSimulate*>* list) {
2044 2631390 : while (!list->is_empty()) {
2045 1430971 : HSimulate* from = list->RemoveLast();
2046 : ZoneList<HValue*>* from_values = &from->values_;
2047 481692 : for (int i = 0; i < from_values->length(); ++i) {
2048 163996 : if (from->HasAssignedIndexAt(i)) {
2049 : int index = from->GetAssignedIndexAt(i);
2050 26526 : if (HasValueForIndex(index)) continue;
2051 257455 : AddAssignedValue(index, from_values->at(i));
2052 : } else {
2053 137470 : if (pop_count_ > 0) {
2054 130960 : pop_count_--;
2055 : } else {
2056 6510 : AddPushedValue(from_values->at(i));
2057 : }
2058 : }
2059 : }
2060 76850 : pop_count_ += from->pop_count_;
2061 76850 : from->DeleteAndReplaceWith(NULL);
2062 : }
2063 1277269 : }
2064 :
2065 :
2066 0 : std::ostream& HSimulate::PrintDataTo(std::ostream& os) const { // NOLINT
2067 0 : os << "id=" << ast_id().ToInt();
2068 0 : if (pop_count_ > 0) os << " pop " << pop_count_;
2069 0 : if (values_.length() > 0) {
2070 0 : if (pop_count_ > 0) os << " /";
2071 0 : for (int i = values_.length() - 1; i >= 0; --i) {
2072 0 : if (HasAssignedIndexAt(i)) {
2073 0 : os << " var[" << GetAssignedIndexAt(i) << "] = ";
2074 : } else {
2075 0 : os << " push ";
2076 : }
2077 0 : os << NameOf(values_[i]);
2078 0 : if (i > 0) os << ",";
2079 : }
2080 : }
2081 0 : return os;
2082 : }
2083 :
2084 :
2085 10771243 : void HSimulate::ReplayEnvironment(HEnvironment* env) {
2086 12062461 : if (is_done_with_replay()) return;
2087 : DCHECK(env != NULL);
2088 : env->set_ast_id(ast_id());
2089 4740004 : env->Drop(pop_count());
2090 8596859 : for (int i = values()->length() - 1; i >= 0; --i) {
2091 3856872 : HValue* value = values()->at(i);
2092 3856872 : if (HasAssignedIndexAt(i)) {
2093 1254949 : env->Bind(GetAssignedIndexAt(i), value);
2094 : } else {
2095 : env->Push(value);
2096 : }
2097 : }
2098 : set_done_with_replay();
2099 : }
2100 :
2101 :
2102 31827 : static void ReplayEnvironmentNested(const ZoneList<HValue*>* values,
2103 8487 : HCapturedObject* other) {
2104 373668 : for (int i = 0; i < values->length(); ++i) {
2105 341841 : HValue* value = values->at(i);
2106 155007 : if (value->IsCapturedObject()) {
2107 16974 : if (HCapturedObject::cast(value)->capture_id() == other->capture_id()) {
2108 4833 : values->at(i) = other;
2109 : } else {
2110 3654 : ReplayEnvironmentNested(HCapturedObject::cast(value)->values(), other);
2111 : }
2112 : }
2113 : }
2114 31827 : }
2115 :
2116 :
2117 : // Replay captured objects by replacing all captured objects with the
2118 : // same capture id in the current and all outer environments.
2119 39134 : void HCapturedObject::ReplayEnvironment(HEnvironment* env) {
2120 : DCHECK(env != NULL);
2121 50095 : while (env != NULL) {
2122 28173 : ReplayEnvironmentNested(env->values(), this);
2123 : env = env->outer();
2124 : }
2125 10961 : }
2126 :
2127 :
2128 0 : std::ostream& HCapturedObject::PrintDataTo(std::ostream& os) const { // NOLINT
2129 0 : os << "#" << capture_id() << " ";
2130 0 : return HDematerializedObject::PrintDataTo(os);
2131 : }
2132 :
2133 :
2134 126898 : void HEnterInlined::RegisterReturnTarget(HBasicBlock* return_target,
2135 : Zone* zone) {
2136 : DCHECK(return_target->IsInlineReturnTarget());
2137 : return_targets_.Add(return_target, zone);
2138 126898 : }
2139 :
2140 :
2141 0 : std::ostream& HEnterInlined::PrintDataTo(std::ostream& os) const { // NOLINT
2142 0 : os << function()->debug_name()->ToCString().get();
2143 0 : if (syntactic_tail_call_mode() == TailCallMode::kAllow) {
2144 0 : os << ", JSTailCall";
2145 : }
2146 0 : return os;
2147 : }
2148 :
2149 :
2150 : static bool IsInteger32(double value) {
2151 624258 : if (value >= std::numeric_limits<int32_t>::min() &&
2152 : value <= std::numeric_limits<int32_t>::max()) {
2153 586626 : double roundtrip_value = static_cast<double>(static_cast<int32_t>(value));
2154 586626 : return bit_cast<int64_t>(roundtrip_value) == bit_cast<int64_t>(value);
2155 : }
2156 : return false;
2157 : }
2158 :
2159 :
2160 128 : HConstant::HConstant(Special special)
2161 : : HTemplateInstruction<0>(HType::TaggedNumber()),
2162 : object_(Handle<Object>::null()),
2163 : object_map_(Handle<Map>::null()),
2164 : bit_field_(HasDoubleValueField::encode(true) |
2165 : InstanceTypeField::encode(kUnknownInstanceType)),
2166 256 : int32_value_(0) {
2167 : DCHECK_EQ(kHoleNaN, special);
2168 : // Manipulating the signaling NaN used for the hole in C++, e.g. with bit_cast
2169 : // will change its value on ia32 (the x87 stack is used to return values
2170 : // and stores to the stack silently clear the signalling bit).
2171 : // Therefore we have to use memcpy for initializing |double_value_| with
2172 : // kHoleNanInt64 here.
2173 128 : std::memcpy(&double_value_, &kHoleNanInt64, sizeof(double_value_));
2174 128 : Initialize(Representation::Double());
2175 128 : }
2176 :
2177 :
2178 4622177 : HConstant::HConstant(Handle<Object> object, Representation r)
2179 : : HTemplateInstruction<0>(HType::FromValue(object)),
2180 : object_(Unique<Object>::CreateUninitialized(object)),
2181 : object_map_(Handle<Map>::null()),
2182 : bit_field_(
2183 : HasStableMapValueField::encode(false) |
2184 : HasSmiValueField::encode(false) | HasInt32ValueField::encode(false) |
2185 : HasDoubleValueField::encode(false) |
2186 : HasExternalReferenceValueField::encode(false) |
2187 4622178 : IsNotInNewSpaceField::encode(true) |
2188 4622176 : BooleanValueField::encode(object->BooleanValue()) |
2189 4622178 : IsUndetectableField::encode(false) | IsCallableField::encode(false) |
2190 13866531 : InstanceTypeField::encode(kUnknownInstanceType)) {
2191 4622178 : if (object->IsNumber()) {
2192 : double n = object->Number();
2193 : bool has_int32_value = IsInteger32(n);
2194 1194224 : bit_field_ = HasInt32ValueField::update(bit_field_, has_int32_value);
2195 597112 : int32_value_ = DoubleToInt32(n);
2196 : bit_field_ = HasSmiValueField::update(
2197 1194224 : bit_field_, has_int32_value && Smi::IsValid(int32_value_));
2198 597112 : if (std::isnan(n)) {
2199 4375 : double_value_ = std::numeric_limits<double>::quiet_NaN();
2200 : // Canonicalize object with NaN value.
2201 : DCHECK(object->IsHeapObject()); // NaN can't be a Smi.
2202 : Isolate* isolate = HeapObject::cast(*object)->GetIsolate();
2203 : object = isolate->factory()->nan_value();
2204 4375 : object_ = Unique<Object>::CreateUninitialized(object);
2205 : } else {
2206 592737 : double_value_ = n;
2207 : // Canonicalize object with -0.0 value.
2208 592737 : if (bit_cast<int64_t>(n) == bit_cast<int64_t>(-0.0)) {
2209 : DCHECK(object->IsHeapObject()); // -0.0 can't be a Smi.
2210 : Isolate* isolate = HeapObject::cast(*object)->GetIsolate();
2211 : object = isolate->factory()->minus_zero_value();
2212 7869 : object_ = Unique<Object>::CreateUninitialized(object);
2213 : }
2214 : }
2215 1194224 : bit_field_ = HasDoubleValueField::update(bit_field_, true);
2216 : }
2217 4622178 : if (object->IsHeapObject()) {
2218 : Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
2219 : Isolate* isolate = heap_object->GetIsolate();
2220 : Handle<Map> map(heap_object->map(), isolate);
2221 : bit_field_ = IsNotInNewSpaceField::update(
2222 8161964 : bit_field_, !isolate->heap()->InNewSpace(*object));
2223 4080982 : bit_field_ = InstanceTypeField::update(bit_field_, map->instance_type());
2224 : bit_field_ =
2225 4080982 : IsUndetectableField::update(bit_field_, map->is_undetectable());
2226 4080982 : bit_field_ = IsCallableField::update(bit_field_, map->is_callable());
2227 4080982 : if (map->is_stable()) object_map_ = Unique<Map>::CreateImmovable(map);
2228 : bit_field_ = HasStableMapValueField::update(
2229 : bit_field_,
2230 8237090 : HasMapValue() && Handle<Map>::cast(heap_object)->is_stable());
2231 : }
2232 :
2233 4622178 : Initialize(r);
2234 4622175 : }
2235 :
2236 :
2237 623995 : HConstant::HConstant(Unique<Object> object, Unique<Map> object_map,
2238 : bool has_stable_map_value, Representation r, HType type,
2239 : bool is_not_in_new_space, bool boolean_value,
2240 : bool is_undetectable, InstanceType instance_type)
2241 : : HTemplateInstruction<0>(type),
2242 : object_(object),
2243 : object_map_(object_map),
2244 : bit_field_(HasStableMapValueField::encode(has_stable_map_value) |
2245 : HasSmiValueField::encode(false) |
2246 : HasInt32ValueField::encode(false) |
2247 : HasDoubleValueField::encode(false) |
2248 623995 : HasExternalReferenceValueField::encode(false) |
2249 623995 : IsNotInNewSpaceField::encode(is_not_in_new_space) |
2250 623995 : BooleanValueField::encode(boolean_value) |
2251 623995 : IsUndetectableField::encode(is_undetectable) |
2252 1247990 : InstanceTypeField::encode(instance_type)) {
2253 : DCHECK(!object.handle().is_null());
2254 : DCHECK(!type.IsTaggedNumber() || type.IsNone());
2255 623995 : Initialize(r);
2256 623995 : }
2257 :
2258 :
2259 3671761 : HConstant::HConstant(int32_t integer_value, Representation r,
2260 : bool is_not_in_new_space, Unique<Object> object)
2261 : : object_(object),
2262 : object_map_(Handle<Map>::null()),
2263 : bit_field_(HasStableMapValueField::encode(false) |
2264 : HasSmiValueField::encode(Smi::IsValid(integer_value)) |
2265 : HasInt32ValueField::encode(true) |
2266 : HasDoubleValueField::encode(true) |
2267 3671761 : HasExternalReferenceValueField::encode(false) |
2268 3671761 : IsNotInNewSpaceField::encode(is_not_in_new_space) |
2269 3671761 : BooleanValueField::encode(integer_value != 0) |
2270 3671761 : IsUndetectableField::encode(false) |
2271 : InstanceTypeField::encode(kUnknownInstanceType)),
2272 : int32_value_(integer_value),
2273 11015283 : double_value_(FastI2D(integer_value)) {
2274 : // It's possible to create a constant with a value in Smi-range but stored
2275 : // in a (pre-existing) HeapNumber. See crbug.com/349878.
2276 3671761 : bool could_be_heapobject = r.IsTagged() && !object.handle().is_null();
2277 3671761 : bool is_smi = HasSmiValue() && !could_be_heapobject;
2278 3671761 : set_type(is_smi ? HType::Smi() : HType::TaggedNumber());
2279 3671761 : Initialize(r);
2280 3671748 : }
2281 :
2282 27146 : HConstant::HConstant(double double_value, Representation r,
2283 : bool is_not_in_new_space, Unique<Object> object)
2284 : : object_(object),
2285 : object_map_(Handle<Map>::null()),
2286 : bit_field_(HasStableMapValueField::encode(false) |
2287 27146 : HasInt32ValueField::encode(IsInteger32(double_value)) |
2288 : HasDoubleValueField::encode(true) |
2289 27146 : HasExternalReferenceValueField::encode(false) |
2290 27146 : IsNotInNewSpaceField::encode(is_not_in_new_space) |
2291 27146 : BooleanValueField::encode(double_value != 0 &&
2292 : !std::isnan(double_value)) |
2293 27146 : IsUndetectableField::encode(false) |
2294 : InstanceTypeField::encode(kUnknownInstanceType)),
2295 54292 : int32_value_(DoubleToInt32(double_value)) {
2296 : bit_field_ = HasSmiValueField::update(
2297 54292 : bit_field_, HasInteger32Value() && Smi::IsValid(int32_value_));
2298 : // It's possible to create a constant with a value in Smi-range but stored
2299 : // in a (pre-existing) HeapNumber. See crbug.com/349878.
2300 27146 : bool could_be_heapobject = r.IsTagged() && !object.handle().is_null();
2301 27146 : bool is_smi = HasSmiValue() && !could_be_heapobject;
2302 27146 : set_type(is_smi ? HType::Smi() : HType::TaggedNumber());
2303 27146 : if (std::isnan(double_value)) {
2304 6412 : double_value_ = std::numeric_limits<double>::quiet_NaN();
2305 : } else {
2306 20734 : double_value_ = double_value;
2307 : }
2308 27146 : Initialize(r);
2309 27146 : }
2310 :
2311 :
2312 11205 : HConstant::HConstant(ExternalReference reference)
2313 : : HTemplateInstruction<0>(HType::Any()),
2314 : object_(Unique<Object>(Handle<Object>::null())),
2315 : object_map_(Handle<Map>::null()),
2316 : bit_field_(
2317 : HasStableMapValueField::encode(false) |
2318 : HasSmiValueField::encode(false) | HasInt32ValueField::encode(false) |
2319 : HasDoubleValueField::encode(false) |
2320 : HasExternalReferenceValueField::encode(true) |
2321 : IsNotInNewSpaceField::encode(true) | BooleanValueField::encode(true) |
2322 : IsUndetectableField::encode(false) |
2323 : InstanceTypeField::encode(kUnknownInstanceType)),
2324 22410 : external_reference_value_(reference) {
2325 11205 : Initialize(Representation::External());
2326 11205 : }
2327 :
2328 :
2329 15801193 : void HConstant::Initialize(Representation r) {
2330 8956313 : if (r.IsNone()) {
2331 : if (HasSmiValue() && SmiValuesAre31Bits()) {
2332 : r = Representation::Smi();
2333 6844880 : } else if (HasInteger32Value()) {
2334 : r = Representation::Integer32();
2335 4082422 : } else if (HasDoubleValue()) {
2336 : r = Representation::Double();
2337 4025066 : } else if (HasExternalReferenceValue()) {
2338 : r = Representation::External();
2339 : } else {
2340 : Handle<Object> object = object_.handle();
2341 4025065 : if (object->IsJSObject()) {
2342 : // Try to eagerly migrate JSObjects that have deprecated maps.
2343 : Handle<JSObject> js_object = Handle<JSObject>::cast(object);
2344 805824 : if (js_object->map()->is_deprecated()) {
2345 8 : JSObject::TryMigrateInstance(js_object);
2346 : }
2347 : }
2348 : r = Representation::Tagged();
2349 : }
2350 : }
2351 8956312 : if (r.IsSmi()) {
2352 : // If we have an existing handle, zap it, because it might be a heap
2353 : // number which we must not re-use when copying this HConstant to
2354 : // Tagged representation later, because having Smi representation now
2355 : // could cause heap object checks not to get emitted.
2356 867898 : object_ = Unique<Object>(Handle<Object>::null());
2357 : }
2358 8956312 : if (r.IsSmiOrInteger32() && object_.handle().is_null()) {
2359 : // If it's not a heap object, it can't be in new space.
2360 6178850 : bit_field_ = IsNotInNewSpaceField::update(bit_field_, true);
2361 : }
2362 : set_representation(r);
2363 : SetFlag(kUseGVN);
2364 8956312 : }
2365 :
2366 :
2367 178835 : bool HConstant::ImmortalImmovable() const {
2368 178835 : if (HasInteger32Value()) {
2369 : return false;
2370 : }
2371 134129 : if (HasDoubleValue()) {
2372 556 : if (IsSpecialDouble()) {
2373 : return true;
2374 : }
2375 305 : return false;
2376 : }
2377 133573 : if (HasExternalReferenceValue()) {
2378 : return false;
2379 : }
2380 :
2381 : DCHECK(!object_.handle().is_null());
2382 16351788 : Heap* heap = isolate()->heap();
2383 : DCHECK(!object_.IsKnownGlobal(heap->minus_zero_value()));
2384 : DCHECK(!object_.IsKnownGlobal(heap->nan_value()));
2385 : return
2386 : #define IMMORTAL_IMMOVABLE_ROOT(name) \
2387 : object_.IsKnownGlobal(heap->root(Heap::k##name##RootIndex)) ||
2388 11909406 : IMMORTAL_IMMOVABLE_ROOT_LIST(IMMORTAL_IMMOVABLE_ROOT)
2389 : #undef IMMORTAL_IMMOVABLE_ROOT
2390 : #define INTERNALIZED_STRING(name, value) \
2391 : object_.IsKnownGlobal(heap->name()) ||
2392 15237488 : INTERNALIZED_STRING_LIST(INTERNALIZED_STRING)
2393 : #undef INTERNALIZED_STRING
2394 : #define STRING_TYPE(NAME, size, name, Name) \
2395 : object_.IsKnownGlobal(heap->name##_map()) ||
2396 1165446 : STRING_TYPE_LIST(STRING_TYPE)
2397 : #undef STRING_TYPE
2398 133572 : false;
2399 : }
2400 :
2401 :
2402 8781235 : bool HConstant::EmitAtUses() {
2403 : DCHECK(IsLinked());
2404 9130962 : if (block()->graph()->has_osr() &&
2405 349727 : block()->graph()->IsStandardConstant(this)) {
2406 : return true;
2407 : }
2408 8741119 : if (HasNoUses()) return true;
2409 8008276 : if (IsCell()) return false;
2410 8008279 : if (representation().IsDouble()) return false;
2411 7874701 : if (representation().IsExternal()) return false;
2412 7855494 : return true;
2413 : }
2414 :
2415 :
2416 3865025 : HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const {
2417 2339000 : if (r.IsSmi() && !HasSmiValue()) return NULL;
2418 1474806 : if (r.IsInteger32() && !HasInteger32Value()) return NULL;
2419 1524317 : if (r.IsDouble() && !HasDoubleValue()) return NULL;
2420 1471208 : if (r.IsExternal() && !HasExternalReferenceValue()) return NULL;
2421 1471208 : if (HasInteger32Value()) {
2422 4336803 : return new (zone) HConstant(int32_value_, r, NotInNewSpace(), object_);
2423 : }
2424 25607 : if (HasDoubleValue()) {
2425 76821 : return new (zone) HConstant(double_value_, r, NotInNewSpace(), object_);
2426 : }
2427 0 : if (HasExternalReferenceValue()) {
2428 0 : return new(zone) HConstant(external_reference_value_);
2429 : }
2430 : DCHECK(!object_.handle().is_null());
2431 : return new (zone) HConstant(object_, object_map_, HasStableMapValue(), r,
2432 : type_, NotInNewSpace(), BooleanValue(),
2433 0 : IsUndetectable(), GetInstanceType());
2434 : }
2435 :
2436 :
2437 3902 : Maybe<HConstant*> HConstant::CopyToTruncatedInt32(Zone* zone) {
2438 : HConstant* res = NULL;
2439 3902 : if (HasInteger32Value()) {
2440 : res = new (zone) HConstant(int32_value_, Representation::Integer32(),
2441 0 : NotInNewSpace(), object_);
2442 3902 : } else if (HasDoubleValue()) {
2443 : res = new (zone)
2444 3839 : HConstant(DoubleToInt32(double_value_), Representation::Integer32(),
2445 11517 : NotInNewSpace(), object_);
2446 : }
2447 3902 : return res != NULL ? Just(res) : Nothing<HConstant*>();
2448 : }
2449 :
2450 :
2451 265471 : Maybe<HConstant*> HConstant::CopyToTruncatedNumber(Isolate* isolate,
2452 : Zone* zone) {
2453 : HConstant* res = NULL;
2454 265471 : Handle<Object> handle = this->handle(isolate);
2455 265471 : if (handle->IsBoolean()) {
2456 4220 : res = handle->BooleanValue() ?
2457 8440 : new(zone) HConstant(1) : new(zone) HConstant(0);
2458 261251 : } else if (handle->IsUndefined(isolate)) {
2459 2104 : res = new (zone) HConstant(std::numeric_limits<double>::quiet_NaN());
2460 260199 : } else if (handle->IsNull(isolate)) {
2461 54 : res = new(zone) HConstant(0);
2462 260172 : } else if (handle->IsString()) {
2463 3760 : res = new(zone) HConstant(String::ToNumber(Handle<String>::cast(handle)));
2464 : }
2465 265471 : return res != NULL ? Just(res) : Nothing<HConstant*>();
2466 : }
2467 :
2468 :
2469 0 : std::ostream& HConstant::PrintDataTo(std::ostream& os) const { // NOLINT
2470 0 : if (HasInteger32Value()) {
2471 0 : os << int32_value_ << " ";
2472 0 : } else if (HasDoubleValue()) {
2473 0 : os << double_value_ << " ";
2474 0 : } else if (HasExternalReferenceValue()) {
2475 0 : os << reinterpret_cast<void*>(external_reference_value_.address()) << " ";
2476 : } else {
2477 : // The handle() method is silently and lazily mutating the object.
2478 0 : Handle<Object> h = const_cast<HConstant*>(this)->handle(isolate());
2479 0 : os << Brief(*h) << " ";
2480 0 : if (HasStableMapValue()) os << "[stable-map] ";
2481 0 : if (HasObjectMap()) os << "[map " << *ObjectMap().handle() << "] ";
2482 : }
2483 0 : if (!NotInNewSpace()) os << "[new space] ";
2484 0 : return os;
2485 : }
2486 :
2487 :
2488 0 : std::ostream& HBinaryOperation::PrintDataTo(std::ostream& os) const { // NOLINT
2489 0 : os << NameOf(left()) << " " << NameOf(right());
2490 0 : if (CheckFlag(kCanOverflow)) os << " !";
2491 0 : if (CheckFlag(kBailoutOnMinusZero)) os << " -0?";
2492 0 : return os;
2493 : }
2494 :
2495 :
2496 993796 : void HBinaryOperation::InferRepresentation(HInferRepresentationPhase* h_infer) {
2497 : DCHECK(CheckFlag(kFlexibleRepresentation));
2498 993796 : Representation new_rep = RepresentationFromInputs();
2499 993794 : UpdateRepresentation(new_rep, h_infer, "inputs");
2500 :
2501 993795 : if (representation().IsSmi() && HasNonSmiUse()) {
2502 : UpdateRepresentation(
2503 47156 : Representation::Integer32(), h_infer, "use requirements");
2504 : }
2505 :
2506 993799 : if (observed_output_representation_.IsNone()) {
2507 440936 : new_rep = RepresentationFromUses();
2508 440936 : UpdateRepresentation(new_rep, h_infer, "uses");
2509 : } else {
2510 552863 : new_rep = RepresentationFromOutput();
2511 552864 : UpdateRepresentation(new_rep, h_infer, "output");
2512 : }
2513 993801 : }
2514 :
2515 :
2516 989777 : Representation HBinaryOperation::RepresentationFromInputs() {
2517 : // Determine the worst case of observed input representations and
2518 : // the currently assumed output representation.
2519 989777 : Representation rep = representation();
2520 2969325 : for (int i = 1; i <= 2; ++i) {
2521 1979549 : rep = rep.generalize(observed_input_representation(i));
2522 : }
2523 : // If any of the actual input representation is more general than what we
2524 : // have so far but not Tagged, use that representation instead.
2525 : Representation left_rep = left()->representation();
2526 : Representation right_rep = right()->representation();
2527 989776 : if (!left_rep.IsTagged()) rep = rep.generalize(left_rep);
2528 989780 : if (!right_rep.IsTagged()) rep = rep.generalize(right_rep);
2529 :
2530 989779 : return rep;
2531 : }
2532 :
2533 :
2534 23735 : bool HBinaryOperation::IgnoreObservedOutputRepresentation(
2535 : Representation current_rep) {
2536 23294 : return ((current_rep.IsInteger32() && CheckUsesForFlag(kTruncatingToInt32)) ||
2537 29930 : (current_rep.IsSmi() && CheckUsesForFlag(kTruncatingToSmi))) &&
2538 : // Mul in Integer32 mode would be too precise.
2539 6823 : (!this->IsMul() || HMul::cast(this)->MulMinusOne());
2540 : }
2541 :
2542 :
2543 552863 : Representation HBinaryOperation::RepresentationFromOutput() {
2544 552863 : Representation rep = representation();
2545 : // Consider observed output representation, but ignore it if it's Double,
2546 : // this instruction is not a division, and all its uses are truncating
2547 : // to Integer32.
2548 576597 : if (observed_output_representation_.is_more_general_than(rep) &&
2549 23735 : !IgnoreObservedOutputRepresentation(rep)) {
2550 19015 : return observed_output_representation_;
2551 : }
2552 : return Representation::None();
2553 : }
2554 :
2555 :
2556 607 : void HBinaryOperation::AssumeRepresentation(Representation r) {
2557 : set_observed_input_representation(1, r);
2558 : set_observed_input_representation(2, r);
2559 607 : HValue::AssumeRepresentation(r);
2560 607 : }
2561 :
2562 :
2563 2203 : void HMathMinMax::InferRepresentation(HInferRepresentationPhase* h_infer) {
2564 : DCHECK(CheckFlag(kFlexibleRepresentation));
2565 2203 : Representation new_rep = RepresentationFromInputs();
2566 2203 : UpdateRepresentation(new_rep, h_infer, "inputs");
2567 : // Do not care about uses.
2568 2203 : }
2569 :
2570 :
2571 96855 : Range* HBitwise::InferRange(Zone* zone) {
2572 96855 : if (op() == Token::BIT_XOR) {
2573 44270 : if (left()->HasRange() && right()->HasRange()) {
2574 : // The maximum value has the high bit, and all bits below, set:
2575 : // (1 << high) - 1.
2576 : // If the range can be negative, the minimum int is a negative number with
2577 : // the high bit, and all bits below, unset:
2578 : // -(1 << high).
2579 : // If it cannot be negative, conservatively choose 0 as minimum int.
2580 22135 : int64_t left_upper = left()->range()->upper();
2581 22135 : int64_t left_lower = left()->range()->lower();
2582 22135 : int64_t right_upper = right()->range()->upper();
2583 22135 : int64_t right_lower = right()->range()->lower();
2584 :
2585 22135 : if (left_upper < 0) left_upper = ~left_upper;
2586 22135 : if (left_lower < 0) left_lower = ~left_lower;
2587 22135 : if (right_upper < 0) right_upper = ~right_upper;
2588 22135 : if (right_lower < 0) right_lower = ~right_lower;
2589 :
2590 : int high = MostSignificantBit(
2591 : static_cast<uint32_t>(
2592 22135 : left_upper | left_lower | right_upper | right_lower));
2593 :
2594 : int64_t limit = 1;
2595 22135 : limit <<= high;
2596 13629 : int32_t min = (left()->range()->CanBeNegative() ||
2597 : right()->range()->CanBeNegative())
2598 30859 : ? static_cast<int32_t>(-limit) : 0;
2599 44270 : return new(zone) Range(min, static_cast<int32_t>(limit - 1));
2600 : }
2601 0 : Range* result = HValue::InferRange(zone);
2602 : result->set_can_be_minus_zero(false);
2603 0 : return result;
2604 : }
2605 : const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff);
2606 74720 : int32_t left_mask = (left()->range() != NULL)
2607 : ? left()->range()->Mask()
2608 74720 : : kDefaultMask;
2609 74720 : int32_t right_mask = (right()->range() != NULL)
2610 : ? right()->range()->Mask()
2611 74720 : : kDefaultMask;
2612 : int32_t result_mask = (op() == Token::BIT_AND)
2613 : ? left_mask & right_mask
2614 74720 : : left_mask | right_mask;
2615 132044 : if (result_mask >= 0) return new(zone) Range(0, result_mask);
2616 :
2617 17396 : Range* result = HValue::InferRange(zone);
2618 : result->set_can_be_minus_zero(false);
2619 17396 : return result;
2620 : }
2621 :
2622 :
2623 13789 : Range* HSar::InferRange(Zone* zone) {
2624 13789 : if (right()->IsConstant()) {
2625 24703 : HConstant* c = HConstant::cast(right());
2626 12356 : if (c->HasInteger32Value()) {
2627 12347 : Range* result = (left()->range() != NULL)
2628 : ? left()->range()->Copy(zone)
2629 12347 : : new(zone) Range();
2630 : result->Sar(c->Integer32Value());
2631 12347 : return result;
2632 : }
2633 : }
2634 1442 : return HValue::InferRange(zone);
2635 : }
2636 :
2637 :
2638 9094 : Range* HShr::InferRange(Zone* zone) {
2639 9094 : if (right()->IsConstant()) {
2640 15903 : HConstant* c = HConstant::cast(right());
2641 7295 : if (c->HasInteger32Value()) {
2642 7288 : int shift_count = c->Integer32Value() & 0x1f;
2643 7288 : if (left()->range()->CanBeNegative()) {
2644 : // Only compute bounds if the result always fits into an int32.
2645 : return (shift_count >= 1)
2646 : ? new(zone) Range(0,
2647 5003 : static_cast<uint32_t>(0xffffffff) >> shift_count)
2648 11936 : : new(zone) Range();
2649 : } else {
2650 : // For positive inputs we can use the >> operator.
2651 : Range* result = (left()->range() != NULL)
2652 : ? left()->range()->Copy(zone)
2653 1320 : : new(zone) Range();
2654 : result->Sar(c->Integer32Value());
2655 1320 : return result;
2656 : }
2657 : }
2658 : }
2659 1806 : return HValue::InferRange(zone);
2660 : }
2661 :
2662 :
2663 16458 : Range* HShl::InferRange(Zone* zone) {
2664 16458 : if (right()->IsConstant()) {
2665 30047 : HConstant* c = HConstant::cast(right());
2666 15027 : if (c->HasInteger32Value()) {
2667 15020 : Range* result = (left()->range() != NULL)
2668 : ? left()->range()->Copy(zone)
2669 15020 : : new(zone) Range();
2670 : result->Shl(c->Integer32Value());
2671 15020 : return result;
2672 : }
2673 : }
2674 1438 : return HValue::InferRange(zone);
2675 : }
2676 :
2677 :
2678 254308 : Range* HLoadNamedField::InferRange(Zone* zone) {
2679 254308 : if (access().representation().IsInteger8()) {
2680 0 : return new(zone) Range(kMinInt8, kMaxInt8);
2681 : }
2682 254308 : if (access().representation().IsUInteger8()) {
2683 22303 : return new(zone) Range(kMinUInt8, kMaxUInt8);
2684 : }
2685 232005 : if (access().representation().IsInteger16()) {
2686 0 : return new(zone) Range(kMinInt16, kMaxInt16);
2687 : }
2688 232005 : if (access().representation().IsUInteger16()) {
2689 0 : return new(zone) Range(kMinUInt16, kMaxUInt16);
2690 : }
2691 232005 : if (access().IsStringLength()) {
2692 18785 : return new(zone) Range(0, String::kMaxLength);
2693 : }
2694 213220 : return HValue::InferRange(zone);
2695 : }
2696 :
2697 :
2698 51620 : Range* HLoadKeyed::InferRange(Zone* zone) {
2699 51620 : switch (elements_kind()) {
2700 : case INT8_ELEMENTS:
2701 163 : return new(zone) Range(kMinInt8, kMaxInt8);
2702 : case UINT8_ELEMENTS:
2703 : case UINT8_CLAMPED_ELEMENTS:
2704 367 : return new(zone) Range(kMinUInt8, kMaxUInt8);
2705 : case INT16_ELEMENTS:
2706 100 : return new(zone) Range(kMinInt16, kMaxInt16);
2707 : case UINT16_ELEMENTS:
2708 112 : return new(zone) Range(kMinUInt16, kMaxUInt16);
2709 : default:
2710 50878 : return HValue::InferRange(zone);
2711 : }
2712 : }
2713 :
2714 :
2715 0 : std::ostream& HCompareGeneric::PrintDataTo(std::ostream& os) const { // NOLINT
2716 0 : os << Token::Name(token()) << " ";
2717 0 : return HBinaryOperation::PrintDataTo(os);
2718 : }
2719 :
2720 :
2721 0 : std::ostream& HStringCompareAndBranch::PrintDataTo(
2722 0 : std::ostream& os) const { // NOLINT
2723 0 : os << Token::Name(token()) << " ";
2724 0 : return HControlInstruction::PrintDataTo(os);
2725 : }
2726 :
2727 :
2728 0 : std::ostream& HCompareNumericAndBranch::PrintDataTo(
2729 0 : std::ostream& os) const { // NOLINT
2730 0 : os << Token::Name(token()) << " " << NameOf(left()) << " " << NameOf(right());
2731 0 : return HControlInstruction::PrintDataTo(os);
2732 : }
2733 :
2734 :
2735 0 : std::ostream& HCompareObjectEqAndBranch::PrintDataTo(
2736 : std::ostream& os) const { // NOLINT
2737 0 : os << NameOf(left()) << " " << NameOf(right());
2738 0 : return HControlInstruction::PrintDataTo(os);
2739 : }
2740 :
2741 :
2742 282685 : bool HCompareObjectEqAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
2743 282685 : if (known_successor_index() != kNoKnownSuccessorIndex) {
2744 0 : *block = SuccessorAt(known_successor_index());
2745 0 : return true;
2746 : }
2747 283110 : if (FLAG_fold_constants && left()->IsConstant() && right()->IsConstant()) {
2748 20 : *block = HConstant::cast(left())->DataEquals(HConstant::cast(right()))
2749 20 : ? FirstSuccessor() : SecondSuccessor();
2750 20 : return true;
2751 : }
2752 282665 : *block = NULL;
2753 282665 : return false;
2754 : }
2755 :
2756 :
2757 3160 : bool HIsStringAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
2758 3160 : if (known_successor_index() != kNoKnownSuccessorIndex) {
2759 12 : *block = SuccessorAt(known_successor_index());
2760 12 : return true;
2761 : }
2762 3162 : if (FLAG_fold_constants && value()->IsConstant()) {
2763 : *block = HConstant::cast(value())->HasStringValue()
2764 0 : ? FirstSuccessor() : SecondSuccessor();
2765 0 : return true;
2766 : }
2767 3148 : if (value()->type().IsString()) {
2768 60 : *block = FirstSuccessor();
2769 60 : return true;
2770 : }
2771 6138 : if (value()->type().IsSmi() ||
2772 3050 : value()->type().IsNull() ||
2773 3050 : value()->type().IsBoolean() ||
2774 6138 : value()->type().IsUndefined() ||
2775 : value()->type().IsJSReceiver()) {
2776 114 : *block = SecondSuccessor();
2777 114 : return true;
2778 : }
2779 2974 : *block = NULL;
2780 2974 : return false;
2781 : }
2782 :
2783 :
2784 8032 : bool HIsUndetectableAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
2785 8032 : if (FLAG_fold_constants && value()->IsConstant()) {
2786 0 : *block = HConstant::cast(value())->IsUndetectable()
2787 0 : ? FirstSuccessor() : SecondSuccessor();
2788 0 : return true;
2789 : }
2790 16003 : if (value()->type().IsNull() || value()->type().IsUndefined()) {
2791 778 : *block = FirstSuccessor();
2792 778 : return true;
2793 : }
2794 14382 : if (value()->type().IsBoolean() ||
2795 6772 : value()->type().IsSmi() ||
2796 13933 : value()->type().IsString() ||
2797 : value()->type().IsJSReceiver()) {
2798 625 : *block = SecondSuccessor();
2799 625 : return true;
2800 : }
2801 6629 : *block = NULL;
2802 6629 : return false;
2803 : }
2804 :
2805 :
2806 12124 : bool HHasInstanceTypeAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
2807 12308 : if (FLAG_fold_constants && value()->IsConstant()) {
2808 34 : InstanceType type = HConstant::cast(value())->GetInstanceType();
2809 34 : *block = (from_ <= type) && (type <= to_)
2810 34 : ? FirstSuccessor() : SecondSuccessor();
2811 34 : return true;
2812 : }
2813 12090 : *block = NULL;
2814 12090 : return false;
2815 : }
2816 :
2817 :
2818 33 : void HCompareHoleAndBranch::InferRepresentation(
2819 : HInferRepresentationPhase* h_infer) {
2820 33 : ChangeRepresentation(value()->representation());
2821 33 : }
2822 :
2823 :
2824 1029383 : bool HCompareNumericAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
2825 1034449 : if (left() == right() &&
2826 : left()->representation().IsSmiOrInteger32()) {
2827 3404 : *block = (token() == Token::EQ ||
2828 514 : token() == Token::EQ_STRICT ||
2829 418 : token() == Token::LTE ||
2830 : token() == Token::GTE)
2831 8802 : ? FirstSuccessor() : SecondSuccessor();
2832 4560 : return true;
2833 : }
2834 1020262 : *block = NULL;
2835 1020262 : return false;
2836 : }
2837 :
2838 :
2839 0 : std::ostream& HGoto::PrintDataTo(std::ostream& os) const { // NOLINT
2840 0 : return os << *SuccessorAt(0);
2841 : }
2842 :
2843 :
2844 321450 : void HCompareNumericAndBranch::InferRepresentation(
2845 : HInferRepresentationPhase* h_infer) {
2846 : Representation left_rep = left()->representation();
2847 : Representation right_rep = right()->representation();
2848 321450 : Representation observed_left = observed_input_representation(0);
2849 321450 : Representation observed_right = observed_input_representation(1);
2850 :
2851 321449 : Representation rep = Representation::None();
2852 321449 : rep = rep.generalize(observed_left);
2853 321449 : rep = rep.generalize(observed_right);
2854 494225 : if (rep.IsNone() || rep.IsSmiOrInteger32()) {
2855 285099 : if (!left_rep.IsTagged()) rep = rep.generalize(left_rep);
2856 285099 : if (!right_rep.IsTagged()) rep = rep.generalize(right_rep);
2857 : } else {
2858 36352 : rep = Representation::Double();
2859 : }
2860 :
2861 321449 : if (rep.IsDouble()) {
2862 : // According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, ===
2863 : // and !=) have special handling of undefined, e.g. undefined == undefined
2864 : // is 'true'. Relational comparisons have a different semantic, first
2865 : // calling ToPrimitive() on their arguments. The standard Crankshaft
2866 : // tagged-to-double conversion to ensure the HCompareNumericAndBranch's
2867 : // inputs are doubles caused 'undefined' to be converted to NaN. That's
2868 : // compatible out-of-the box with ordered relational comparisons (<, >, <=,
2869 : // >=). However, for equality comparisons (and for 'in' and 'instanceof'),
2870 : // it is not consistent with the spec. For example, it would cause undefined
2871 : // == undefined (should be true) to be evaluated as NaN == NaN
2872 : // (false). Therefore, any comparisons other than ordered relational
2873 : // comparisons must cause a deopt when one of their arguments is undefined.
2874 : // See also v8:1434
2875 74168 : if (Token::IsOrderedRelationalCompareOp(token_)) {
2876 : SetFlag(kTruncatingToNumber);
2877 : }
2878 : }
2879 321449 : ChangeRepresentation(rep);
2880 321449 : }
2881 :
2882 :
2883 0 : std::ostream& HParameter::PrintDataTo(std::ostream& os) const { // NOLINT
2884 0 : return os << index();
2885 : }
2886 :
2887 :
2888 0 : std::ostream& HLoadNamedField::PrintDataTo(std::ostream& os) const { // NOLINT
2889 0 : os << NameOf(object()) << access_;
2890 :
2891 0 : if (maps() != NULL) {
2892 0 : os << " [" << *maps()->at(0).handle();
2893 0 : for (int i = 1; i < maps()->size(); ++i) {
2894 0 : os << "," << *maps()->at(i).handle();
2895 : }
2896 0 : os << "]";
2897 : }
2898 :
2899 0 : if (HasDependency()) os << " " << NameOf(dependency());
2900 0 : return os;
2901 : }
2902 :
2903 :
2904 0 : std::ostream& HLoadKeyed::PrintDataTo(std::ostream& os) const { // NOLINT
2905 0 : if (!is_fixed_typed_array()) {
2906 0 : os << NameOf(elements());
2907 : } else {
2908 : DCHECK(elements_kind() >= FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND &&
2909 : elements_kind() <= LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
2910 0 : os << NameOf(elements()) << "." << ElementsKindToString(elements_kind());
2911 : }
2912 :
2913 0 : os << "[" << NameOf(key());
2914 0 : if (IsDehoisted()) os << " + " << base_offset();
2915 0 : os << "]";
2916 :
2917 0 : if (HasDependency()) os << " " << NameOf(dependency());
2918 0 : if (RequiresHoleCheck()) os << " check_hole";
2919 0 : return os;
2920 : }
2921 :
2922 :
2923 8066 : bool HLoadKeyed::TryIncreaseBaseOffset(uint32_t increase_by_value) {
2924 : // The base offset is usually simply the size of the array header, except
2925 : // with dehoisting adds an addition offset due to a array index key
2926 : // manipulation, in which case it becomes (array header size +
2927 : // constant-offset-from-key * kPointerSize)
2928 8066 : uint32_t base_offset = BaseOffsetField::decode(bit_field_);
2929 : v8::base::internal::CheckedNumeric<uint32_t> addition_result = base_offset;
2930 : addition_result += increase_by_value;
2931 8066 : if (!addition_result.IsValid()) return false;
2932 8066 : base_offset = addition_result.ValueOrDie();
2933 8066 : if (!BaseOffsetField::is_valid(base_offset)) return false;
2934 8050 : bit_field_ = BaseOffsetField::update(bit_field_, base_offset);
2935 8050 : return true;
2936 : }
2937 :
2938 :
2939 22229 : bool HLoadKeyed::UsesMustHandleHole() const {
2940 22229 : if (IsFastPackedElementsKind(elements_kind())) {
2941 : return false;
2942 : }
2943 :
2944 22229 : if (IsFixedTypedArrayElementsKind(elements_kind())) {
2945 : return false;
2946 : }
2947 :
2948 22229 : if (hole_mode() == ALLOW_RETURN_HOLE) {
2949 17854 : if (IsFastDoubleElementsKind(elements_kind())) {
2950 810 : return AllUsesCanTreatHoleAsNaN();
2951 : }
2952 : return true;
2953 : }
2954 :
2955 4375 : if (IsFastDoubleElementsKind(elements_kind())) {
2956 : return false;
2957 : }
2958 :
2959 : // Holes are only returned as tagged values.
2960 3960 : if (!representation().IsTagged()) {
2961 : return false;
2962 : }
2963 :
2964 2576 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
2965 4913 : HValue* use = it.value();
2966 4913 : if (!use->IsChange()) return false;
2967 : }
2968 :
2969 144 : return true;
2970 : }
2971 :
2972 :
2973 810 : bool HLoadKeyed::AllUsesCanTreatHoleAsNaN() const {
2974 1620 : return IsFastDoubleElementsKind(elements_kind()) &&
2975 1620 : CheckUsesForFlag(HValue::kTruncatingToNumber);
2976 : }
2977 :
2978 :
2979 103441 : bool HLoadKeyed::RequiresHoleCheck() const {
2980 103441 : if (IsFastPackedElementsKind(elements_kind())) {
2981 : return false;
2982 : }
2983 :
2984 27573 : if (IsFixedTypedArrayElementsKind(elements_kind())) {
2985 : return false;
2986 : }
2987 :
2988 27573 : if (hole_mode() == CONVERT_HOLE_TO_UNDEFINED) {
2989 : return false;
2990 : }
2991 :
2992 22229 : return !UsesMustHandleHole();
2993 : }
2994 :
2995 1007762 : HValue* HCallWithDescriptor::Canonicalize() {
2996 1007762 : if (kind() != Code::KEYED_LOAD_IC) return this;
2997 :
2998 : // Recognize generic keyed loads that use property name generated
2999 : // by for-in statement as a key and rewrite them into fast property load
3000 : // by index.
3001 : typedef LoadWithVectorDescriptor Descriptor;
3002 : HValue* key = parameter(Descriptor::kName);
3003 72411 : if (key->IsLoadKeyed()) {
3004 : HLoadKeyed* key_load = HLoadKeyed::cast(key);
3005 2763 : if (key_load->elements()->IsForInCacheArray()) {
3006 594 : HForInCacheArray* names_cache =
3007 : HForInCacheArray::cast(key_load->elements());
3008 :
3009 : HValue* object = parameter(Descriptor::kReceiver);
3010 652 : if (names_cache->enumerable() == object) {
3011 : HForInCacheArray* index_cache =
3012 : names_cache->index_cache();
3013 : HCheckMapValue* map_check = HCheckMapValue::New(
3014 : block()->graph()->isolate(), block()->graph()->zone(),
3015 2376 : block()->graph()->GetInvalidContext(), object, names_cache->map());
3016 : HInstruction* index = HLoadKeyed::New(
3017 : block()->graph()->isolate(), block()->graph()->zone(),
3018 594 : block()->graph()->GetInvalidContext(), index_cache, key_load->key(),
3019 594 : key_load->key(), nullptr, key_load->elements_kind());
3020 594 : map_check->InsertBefore(this);
3021 594 : index->InsertBefore(this);
3022 1782 : return Prepend(new (block()->zone()) HLoadFieldByIndex(object, index));
3023 : }
3024 : }
3025 : }
3026 71817 : return this;
3027 : }
3028 :
3029 0 : std::ostream& HStoreNamedField::PrintDataTo(std::ostream& os) const { // NOLINT
3030 0 : os << NameOf(object()) << access_ << " = " << NameOf(value());
3031 0 : if (NeedsWriteBarrier()) os << " (write-barrier)";
3032 0 : if (has_transition()) os << " (transition map " << *transition_map() << ")";
3033 0 : return os;
3034 : }
3035 :
3036 :
3037 0 : std::ostream& HStoreKeyed::PrintDataTo(std::ostream& os) const { // NOLINT
3038 0 : if (!is_fixed_typed_array()) {
3039 0 : os << NameOf(elements());
3040 : } else {
3041 : DCHECK(elements_kind() >= FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND &&
3042 : elements_kind() <= LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
3043 0 : os << NameOf(elements()) << "." << ElementsKindToString(elements_kind());
3044 : }
3045 :
3046 0 : os << "[" << NameOf(key());
3047 0 : if (IsDehoisted()) os << " + " << base_offset();
3048 0 : return os << "] = " << NameOf(value());
3049 : }
3050 :
3051 :
3052 0 : std::ostream& HTransitionElementsKind::PrintDataTo(
3053 : std::ostream& os) const { // NOLINT
3054 0 : os << NameOf(object());
3055 : ElementsKind from_kind = original_map().handle()->elements_kind();
3056 : ElementsKind to_kind = transitioned_map().handle()->elements_kind();
3057 0 : os << " " << *original_map().handle() << " ["
3058 0 : << ElementsAccessor::ForKind(from_kind)->name() << "] -> "
3059 0 : << *transitioned_map().handle() << " ["
3060 0 : << ElementsAccessor::ForKind(to_kind)->name() << "]";
3061 0 : if (IsSimpleMapChangeTransition(from_kind, to_kind)) os << " (simple)";
3062 0 : return os;
3063 : }
3064 :
3065 :
3066 0 : std::ostream& HInnerAllocatedObject::PrintDataTo(
3067 : std::ostream& os) const { // NOLINT
3068 0 : os << NameOf(base_object()) << " offset ";
3069 0 : return offset()->PrintTo(os);
3070 : }
3071 :
3072 :
3073 0 : std::ostream& HLoadContextSlot::PrintDataTo(std::ostream& os) const { // NOLINT
3074 0 : return os << NameOf(value()) << "[" << slot_index() << "]";
3075 : }
3076 :
3077 :
3078 0 : std::ostream& HStoreContextSlot::PrintDataTo(
3079 0 : std::ostream& os) const { // NOLINT
3080 0 : return os << NameOf(context()) << "[" << slot_index()
3081 0 : << "] = " << NameOf(value());
3082 : }
3083 :
3084 :
3085 : // Implementation of type inference and type conversions. Calculates
3086 : // the inferred type of this instruction based on the input operands.
3087 :
3088 27945343 : HType HValue::CalculateInferredType() {
3089 27945343 : return type_;
3090 : }
3091 :
3092 :
3093 424238 : HType HPhi::CalculateInferredType() {
3094 424238 : if (OperandCount() == 0) return HType::Tagged();
3095 : HType result = OperandAt(0)->type();
3096 947156 : for (int i = 1; i < OperandCount(); ++i) {
3097 : HType current = OperandAt(i)->type();
3098 : result = result.Combine(current);
3099 : }
3100 424238 : return result;
3101 : }
3102 :
3103 :
3104 509131 : HType HChange::CalculateInferredType() {
3105 509131 : if (from().IsDouble() && to().IsTagged()) return HType::HeapNumber();
3106 : return type();
3107 : }
3108 :
3109 :
3110 33315 : Representation HUnaryMathOperation::RepresentationFromInputs() {
3111 66630 : if (SupportsFlexibleFloorAndRound() &&
3112 33315 : (op_ == kMathFloor || op_ == kMathRound)) {
3113 : // Floor and Round always take a double input. The integral result can be
3114 : // used as an integer or a double. Infer the representation from the uses.
3115 : return Representation::None();
3116 : }
3117 630 : Representation rep = representation();
3118 : // If any of the actual input representation is more general than what we
3119 : // have so far but not Tagged, use that representation instead.
3120 : Representation input_rep = value()->representation();
3121 630 : if (!input_rep.IsTagged()) {
3122 528 : rep = rep.generalize(input_rep);
3123 : }
3124 630 : return rep;
3125 : }
3126 :
3127 :
3128 19281 : bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect,
3129 7737 : HValue* dominator) {
3130 : DCHECK(side_effect == kNewSpacePromotion);
3131 : DCHECK(!IsAllocationFolded());
3132 21355 : Zone* zone = block()->zone();
3133 19281 : Isolate* isolate = block()->isolate();
3134 19281 : if (!FLAG_use_allocation_folding) return false;
3135 :
3136 : // Try to fold allocations together with their dominating allocations.
3137 19168 : if (!dominator->IsAllocate()) {
3138 15993 : if (FLAG_trace_allocation_folding) {
3139 : PrintF("#%d (%s) cannot fold into #%d (%s)\n",
3140 0 : id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
3141 : }
3142 : return false;
3143 : }
3144 :
3145 : // Check whether we are folding within the same block for local folding.
3146 3175 : if (FLAG_use_local_allocation_folding && dominator->block() != block()) {
3147 0 : if (FLAG_trace_allocation_folding) {
3148 : PrintF("#%d (%s) cannot fold into #%d (%s), crosses basic blocks\n",
3149 0 : id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
3150 : }
3151 : return false;
3152 : }
3153 :
3154 3236 : HAllocate* dominator_allocate = HAllocate::cast(dominator);
3155 : HValue* dominator_size = dominator_allocate->size();
3156 : HValue* current_size = size();
3157 :
3158 : // TODO(hpayer): Add support for non-constant allocation in dominator.
3159 6017 : if (!current_size->IsInteger32Constant() ||
3160 : !dominator_size->IsInteger32Constant()) {
3161 341 : if (FLAG_trace_allocation_folding) {
3162 : PrintF("#%d (%s) cannot fold into #%d (%s), "
3163 : "dynamic allocation size in dominator\n",
3164 0 : id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
3165 : }
3166 : return false;
3167 : }
3168 :
3169 2834 : if (IsAllocationFoldingDominator()) {
3170 5 : if (FLAG_trace_allocation_folding) {
3171 : PrintF("#%d (%s) cannot fold into #%d (%s), already dominator\n", id(),
3172 0 : Mnemonic(), dominator->id(), dominator->Mnemonic());
3173 : }
3174 : return false;
3175 : }
3176 :
3177 2829 : if (!IsFoldable(dominator_allocate)) {
3178 0 : if (FLAG_trace_allocation_folding) {
3179 : PrintF("#%d (%s) cannot fold into #%d (%s), different spaces\n", id(),
3180 0 : Mnemonic(), dominator->id(), dominator->Mnemonic());
3181 : }
3182 : return false;
3183 : }
3184 :
3185 : DCHECK(
3186 : (IsNewSpaceAllocation() && dominator_allocate->IsNewSpaceAllocation()) ||
3187 : (IsOldSpaceAllocation() && dominator_allocate->IsOldSpaceAllocation()));
3188 :
3189 : // First update the size of the dominator allocate instruction.
3190 : dominator_size = dominator_allocate->size();
3191 : int32_t original_object_size =
3192 : HConstant::cast(dominator_size)->GetInteger32Constant();
3193 : int32_t dominator_size_constant = original_object_size;
3194 :
3195 2829 : if (MustAllocateDoubleAligned()) {
3196 407 : if ((dominator_size_constant & kDoubleAlignmentMask) != 0) {
3197 0 : dominator_size_constant += kDoubleSize / 2;
3198 : }
3199 : }
3200 :
3201 : int32_t current_size_max_value = size()->GetInteger32Constant();
3202 2829 : int32_t new_dominator_size = dominator_size_constant + current_size_max_value;
3203 :
3204 : // Since we clear the first word after folded memory, we cannot use the
3205 : // whole kMaxRegularHeapObjectSize memory.
3206 2829 : if (new_dominator_size > kMaxRegularHeapObjectSize - kPointerSize) {
3207 0 : if (FLAG_trace_allocation_folding) {
3208 : PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n",
3209 : id(), Mnemonic(), dominator_allocate->id(),
3210 0 : dominator_allocate->Mnemonic(), new_dominator_size);
3211 : }
3212 : return false;
3213 : }
3214 :
3215 : HInstruction* new_dominator_size_value = HConstant::CreateAndInsertBefore(
3216 : isolate, zone, context(), new_dominator_size, Representation::None(),
3217 : dominator_allocate);
3218 :
3219 : dominator_allocate->UpdateSize(new_dominator_size_value);
3220 :
3221 2829 : if (MustAllocateDoubleAligned()) {
3222 407 : if (!dominator_allocate->MustAllocateDoubleAligned()) {
3223 : dominator_allocate->MakeDoubleAligned();
3224 : }
3225 : }
3226 :
3227 2829 : if (!dominator_allocate->IsAllocationFoldingDominator()) {
3228 : HAllocate* first_alloc =
3229 : HAllocate::New(isolate, zone, dominator_allocate->context(),
3230 : dominator_size, dominator_allocate->type(),
3231 : IsNewSpaceAllocation() ? NOT_TENURED : TENURED,
3232 6222 : JS_OBJECT_TYPE, block()->graph()->GetConstant0());
3233 2074 : first_alloc->InsertAfter(dominator_allocate);
3234 2074 : dominator_allocate->ReplaceAllUsesWith(first_alloc);
3235 : dominator_allocate->MakeAllocationFoldingDominator();
3236 2074 : first_alloc->MakeFoldedAllocation(dominator_allocate);
3237 2074 : if (FLAG_trace_allocation_folding) {
3238 : PrintF("#%d (%s) inserted for dominator #%d (%s)\n", first_alloc->id(),
3239 : first_alloc->Mnemonic(), dominator_allocate->id(),
3240 0 : dominator_allocate->Mnemonic());
3241 : }
3242 : }
3243 :
3244 2829 : MakeFoldedAllocation(dominator_allocate);
3245 :
3246 2829 : if (FLAG_trace_allocation_folding) {
3247 : PrintF("#%d (%s) folded into #%d (%s), new dominator size: %d\n", id(),
3248 : Mnemonic(), dominator_allocate->id(), dominator_allocate->Mnemonic(),
3249 0 : new_dominator_size);
3250 : }
3251 : return true;
3252 : }
3253 :
3254 :
3255 0 : std::ostream& HAllocate::PrintDataTo(std::ostream& os) const { // NOLINT
3256 0 : os << NameOf(size()) << " (";
3257 0 : if (IsNewSpaceAllocation()) os << "N";
3258 0 : if (IsOldSpaceAllocation()) os << "P";
3259 0 : if (MustAllocateDoubleAligned()) os << "A";
3260 0 : if (MustPrefillWithFiller()) os << "F";
3261 0 : if (IsAllocationFoldingDominator()) os << "d";
3262 0 : if (IsAllocationFolded()) os << "f";
3263 0 : return os << ")";
3264 : }
3265 :
3266 :
3267 1199 : bool HStoreKeyed::TryIncreaseBaseOffset(uint32_t increase_by_value) {
3268 : // The base offset is usually simply the size of the array header, except
3269 : // with dehoisting adds an addition offset due to a array index key
3270 : // manipulation, in which case it becomes (array header size +
3271 : // constant-offset-from-key * kPointerSize)
3272 1199 : v8::base::internal::CheckedNumeric<uint32_t> addition_result = base_offset_;
3273 : addition_result += increase_by_value;
3274 1199 : if (!addition_result.IsValid()) return false;
3275 1199 : base_offset_ = addition_result.ValueOrDie();
3276 1199 : return true;
3277 : }
3278 :
3279 :
3280 5963 : bool HStoreKeyed::NeedsCanonicalization() {
3281 5963 : switch (value()->opcode()) {
3282 : case kLoadKeyed: {
3283 : ElementsKind load_kind = HLoadKeyed::cast(value())->elements_kind();
3284 5151 : return IsFixedFloatElementsKind(load_kind);
3285 : }
3286 : case kChange: {
3287 : Representation from = HChange::cast(value())->from();
3288 159 : return from.IsTagged() || from.IsHeapObject();
3289 : }
3290 : case kConstant:
3291 : // Double constants are canonicalized upon construction.
3292 : return false;
3293 : default:
3294 276 : return !value()->IsBinaryOperation();
3295 : }
3296 : }
3297 :
3298 :
3299 : #define H_CONSTANT_INT(val) \
3300 : HConstant::New(isolate, zone, context, static_cast<int32_t>(val))
3301 : #define H_CONSTANT_DOUBLE(val) \
3302 : HConstant::New(isolate, zone, context, static_cast<double>(val))
3303 :
3304 : #define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op) \
3305 : HInstruction* HInstr::New(Isolate* isolate, Zone* zone, HValue* context, \
3306 : HValue* left, HValue* right) { \
3307 : if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) { \
3308 : HConstant* c_left = HConstant::cast(left); \
3309 : HConstant* c_right = HConstant::cast(right); \
3310 : if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
3311 : double double_res = c_left->DoubleValue() op c_right->DoubleValue(); \
3312 : if (IsInt32Double(double_res)) { \
3313 : return H_CONSTANT_INT(double_res); \
3314 : } \
3315 : return H_CONSTANT_DOUBLE(double_res); \
3316 : } \
3317 : } \
3318 : return new (zone) HInstr(context, left, right); \
3319 : }
3320 :
3321 577957 : DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HAdd, +)
3322 54908 : DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HMul, *)
3323 52808 : DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HSub, -)
3324 :
3325 : #undef DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR
3326 :
3327 :
3328 26867 : HInstruction* HStringAdd::New(Isolate* isolate, Zone* zone, HValue* context,
3329 : HValue* left, HValue* right,
3330 : PretenureFlag pretenure_flag,
3331 : StringAddFlags flags,
3332 : Handle<AllocationSite> allocation_site) {
3333 26889 : if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3334 : HConstant* c_right = HConstant::cast(right);
3335 : HConstant* c_left = HConstant::cast(left);
3336 20 : if (c_left->HasStringValue() && c_right->HasStringValue()) {
3337 : Handle<String> left_string = c_left->StringValue();
3338 : Handle<String> right_string = c_right->StringValue();
3339 : // Prevent possible exception by invalid string length.
3340 10 : if (left_string->length() + right_string->length() < String::kMaxLength) {
3341 : MaybeHandle<String> concat = isolate->factory()->NewConsString(
3342 10 : c_left->StringValue(), c_right->StringValue());
3343 10 : return HConstant::New(isolate, zone, context, concat.ToHandleChecked());
3344 : }
3345 : }
3346 : }
3347 : return new (zone)
3348 53714 : HStringAdd(context, left, right, pretenure_flag, flags, allocation_site);
3349 : }
3350 :
3351 :
3352 0 : std::ostream& HStringAdd::PrintDataTo(std::ostream& os) const { // NOLINT
3353 0 : if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
3354 0 : os << "_CheckBoth";
3355 0 : } else if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_LEFT) {
3356 0 : os << "_CheckLeft";
3357 0 : } else if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_RIGHT) {
3358 0 : os << "_CheckRight";
3359 : }
3360 0 : HBinaryOperation::PrintDataTo(os);
3361 0 : os << " (";
3362 0 : if (pretenure_flag() == NOT_TENURED)
3363 0 : os << "N";
3364 0 : else if (pretenure_flag() == TENURED)
3365 0 : os << "D";
3366 0 : return os << ")";
3367 : }
3368 :
3369 :
3370 516 : HInstruction* HStringCharFromCode::New(Isolate* isolate, Zone* zone,
3371 : HValue* context, HValue* char_code) {
3372 526 : if (FLAG_fold_constants && char_code->IsConstant()) {
3373 14 : HConstant* c_code = HConstant::cast(char_code);
3374 10 : if (c_code->HasNumberValue()) {
3375 10 : if (std::isfinite(c_code->DoubleValue())) {
3376 4 : uint32_t code = c_code->NumberValueAsInteger32() & 0xffff;
3377 : return HConstant::New(
3378 : isolate, zone, context,
3379 8 : isolate->factory()->LookupSingleCharacterStringFromCode(code));
3380 : }
3381 : return HConstant::New(isolate, zone, context,
3382 6 : isolate->factory()->empty_string());
3383 : }
3384 : }
3385 506 : return new(zone) HStringCharFromCode(context, char_code);
3386 : }
3387 :
3388 :
3389 29396 : HInstruction* HUnaryMathOperation::New(Isolate* isolate, Zone* zone,
3390 : HValue* context, HValue* value,
3391 : BuiltinFunctionId op) {
3392 : do {
3393 29396 : if (!FLAG_fold_constants) break;
3394 108 : if (!value->IsConstant()) break;
3395 108 : HConstant* constant = HConstant::cast(value);
3396 108 : if (!constant->HasNumberValue()) break;
3397 : double d = constant->DoubleValue();
3398 108 : if (std::isnan(d)) { // NaN poisons everything.
3399 14 : return H_CONSTANT_DOUBLE(std::numeric_limits<double>::quiet_NaN());
3400 : }
3401 94 : if (std::isinf(d)) { // +Infinity and -Infinity.
3402 40 : switch (op) {
3403 : case kMathCos:
3404 : case kMathSin:
3405 0 : return H_CONSTANT_DOUBLE(std::numeric_limits<double>::quiet_NaN());
3406 : case kMathExp:
3407 4 : return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0);
3408 : case kMathLog:
3409 : case kMathSqrt:
3410 8 : return H_CONSTANT_DOUBLE(
3411 : (d > 0.0) ? d : std::numeric_limits<double>::quiet_NaN());
3412 : case kMathPowHalf:
3413 : case kMathAbs:
3414 16 : return H_CONSTANT_DOUBLE((d > 0.0) ? d : -d);
3415 : case kMathRound:
3416 : case kMathFround:
3417 : case kMathFloor:
3418 12 : return H_CONSTANT_DOUBLE(d);
3419 : case kMathClz32:
3420 0 : return H_CONSTANT_INT(32);
3421 : default:
3422 0 : UNREACHABLE();
3423 : break;
3424 : }
3425 : }
3426 54 : switch (op) {
3427 : case kMathCos:
3428 0 : return H_CONSTANT_DOUBLE(base::ieee754::cos(d));
3429 : case kMathExp:
3430 6 : return H_CONSTANT_DOUBLE(base::ieee754::exp(d));
3431 : case kMathLog:
3432 6 : return H_CONSTANT_DOUBLE(base::ieee754::log(d));
3433 : case kMathSin:
3434 0 : return H_CONSTANT_DOUBLE(base::ieee754::sin(d));
3435 : case kMathSqrt:
3436 6 : lazily_initialize_fast_sqrt(isolate);
3437 6 : return H_CONSTANT_DOUBLE(fast_sqrt(d, isolate));
3438 : case kMathPowHalf:
3439 2 : return H_CONSTANT_DOUBLE(power_double_double(d, 0.5));
3440 : case kMathAbs:
3441 4 : return H_CONSTANT_DOUBLE((d >= 0.0) ? d + 0.0 : -d);
3442 : case kMathRound:
3443 : // -0.5 .. -0.0 round to -0.0.
3444 18 : if ((d >= -0.5 && Double(d).Sign() < 0)) return H_CONSTANT_DOUBLE(-0.0);
3445 : // Doubles are represented as Significant * 2 ^ Exponent. If the
3446 : // Exponent is not negative, the double value is already an integer.
3447 8 : if (Double(d).Exponent() >= 0) return H_CONSTANT_DOUBLE(d);
3448 12 : return H_CONSTANT_DOUBLE(Floor(d + 0.5));
3449 : case kMathFround:
3450 10 : return H_CONSTANT_DOUBLE(static_cast<double>(static_cast<float>(d)));
3451 : case kMathFloor:
3452 10 : return H_CONSTANT_DOUBLE(Floor(d));
3453 : case kMathClz32: {
3454 : uint32_t i = DoubleToUint32(d);
3455 0 : return H_CONSTANT_INT(base::bits::CountLeadingZeros32(i));
3456 : }
3457 : default:
3458 0 : UNREACHABLE();
3459 : break;
3460 : }
3461 : } while (false);
3462 29288 : return new(zone) HUnaryMathOperation(context, value, op);
3463 : }
3464 :
3465 :
3466 33315 : Representation HUnaryMathOperation::RepresentationFromUses() {
3467 33315 : if (op_ != kMathFloor && op_ != kMathRound) {
3468 630 : return HValue::RepresentationFromUses();
3469 : }
3470 :
3471 : // The instruction can have an int32 or double output. Prefer a double
3472 : // representation if there are double uses.
3473 : bool use_double = false;
3474 :
3475 29912 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
3476 35928 : HValue* use = it.value();
3477 35928 : int use_index = it.index();
3478 35928 : Representation rep_observed = use->observed_input_representation(use_index);
3479 35928 : Representation rep_required = use->RequiredInputRepresentation(use_index);
3480 69388 : use_double |= (rep_observed.IsDouble() || rep_required.IsDouble());
3481 35928 : if (use_double && !FLAG_trace_representation) {
3482 : // Having seen one double is enough.
3483 : break;
3484 : }
3485 29912 : if (FLAG_trace_representation) {
3486 0 : if (!rep_required.IsDouble() || rep_observed.IsDouble()) {
3487 : PrintF("#%d %s is used by #%d %s as %s%s\n",
3488 : id(), Mnemonic(), use->id(),
3489 : use->Mnemonic(), rep_observed.Mnemonic(),
3490 0 : (use->CheckFlag(kTruncatingToInt32) ? "-trunc" : ""));
3491 : } else {
3492 : PrintF("#%d %s is required by #%d %s as %s%s\n",
3493 : id(), Mnemonic(), use->id(),
3494 : use->Mnemonic(), rep_required.Mnemonic(),
3495 0 : (use->CheckFlag(kTruncatingToInt32) ? "-trunc" : ""));
3496 : }
3497 : }
3498 : }
3499 32685 : return use_double ? Representation::Double() : Representation::Integer32();
3500 : }
3501 :
3502 :
3503 989 : HInstruction* HPower::New(Isolate* isolate, Zone* zone, HValue* context,
3504 : HValue* left, HValue* right) {
3505 1025 : if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3506 18 : HConstant* c_left = HConstant::cast(left);
3507 18 : HConstant* c_right = HConstant::cast(right);
3508 36 : if (c_left->HasNumberValue() && c_right->HasNumberValue()) {
3509 : double result =
3510 18 : power_helper(isolate, c_left->DoubleValue(), c_right->DoubleValue());
3511 18 : return H_CONSTANT_DOUBLE(std::isnan(result)
3512 : ? std::numeric_limits<double>::quiet_NaN()
3513 : : result);
3514 : }
3515 : }
3516 971 : return new(zone) HPower(left, right);
3517 : }
3518 :
3519 :
3520 1751 : HInstruction* HMathMinMax::New(Isolate* isolate, Zone* zone, HValue* context,
3521 : HValue* left, HValue* right, Operation op) {
3522 1823 : if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3523 36 : HConstant* c_left = HConstant::cast(left);
3524 36 : HConstant* c_right = HConstant::cast(right);
3525 72 : if (c_left->HasNumberValue() && c_right->HasNumberValue()) {
3526 : double d_left = c_left->DoubleValue();
3527 : double d_right = c_right->DoubleValue();
3528 36 : if (op == kMathMin) {
3529 18 : if (d_left > d_right) return H_CONSTANT_DOUBLE(d_right);
3530 14 : if (d_left < d_right) return H_CONSTANT_DOUBLE(d_left);
3531 10 : if (d_left == d_right) {
3532 : // Handle +0 and -0.
3533 8 : return H_CONSTANT_DOUBLE((Double(d_left).Sign() == -1) ? d_left
3534 : : d_right);
3535 : }
3536 : } else {
3537 18 : if (d_left < d_right) return H_CONSTANT_DOUBLE(d_right);
3538 14 : if (d_left > d_right) return H_CONSTANT_DOUBLE(d_left);
3539 10 : if (d_left == d_right) {
3540 : // Handle +0 and -0.
3541 8 : return H_CONSTANT_DOUBLE((Double(d_left).Sign() == -1) ? d_right
3542 : : d_left);
3543 : }
3544 : }
3545 : // All comparisons failed, must be NaN.
3546 4 : return H_CONSTANT_DOUBLE(std::numeric_limits<double>::quiet_NaN());
3547 : }
3548 : }
3549 1715 : return new(zone) HMathMinMax(context, left, right, op);
3550 : }
3551 :
3552 5637 : HInstruction* HMod::New(Isolate* isolate, Zone* zone, HValue* context,
3553 : HValue* left, HValue* right) {
3554 5650 : if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3555 4 : HConstant* c_left = HConstant::cast(left);
3556 4 : HConstant* c_right = HConstant::cast(right);
3557 4 : if (c_left->HasInteger32Value() && c_right->HasInteger32Value()) {
3558 : int32_t dividend = c_left->Integer32Value();
3559 : int32_t divisor = c_right->Integer32Value();
3560 2 : if (dividend == kMinInt && divisor == -1) {
3561 2 : return H_CONSTANT_DOUBLE(-0.0);
3562 : }
3563 0 : if (divisor != 0) {
3564 0 : int32_t res = dividend % divisor;
3565 0 : if ((res == 0) && (dividend < 0)) {
3566 0 : return H_CONSTANT_DOUBLE(-0.0);
3567 : }
3568 0 : return H_CONSTANT_INT(res);
3569 : }
3570 : }
3571 : }
3572 5635 : return new (zone) HMod(context, left, right);
3573 : }
3574 :
3575 52481 : HInstruction* HDiv::New(Isolate* isolate, Zone* zone, HValue* context,
3576 : HValue* left, HValue* right) {
3577 : // If left and right are constant values, try to return a constant value.
3578 52902 : if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3579 126 : HConstant* c_left = HConstant::cast(left);
3580 204 : HConstant* c_right = HConstant::cast(right);
3581 252 : if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
3582 244 : if (std::isnan(c_left->DoubleValue()) ||
3583 : std::isnan(c_right->DoubleValue())) {
3584 40 : return H_CONSTANT_DOUBLE(std::numeric_limits<double>::quiet_NaN());
3585 86 : } else if (c_right->DoubleValue() != 0) {
3586 32 : double double_res = c_left->DoubleValue() / c_right->DoubleValue();
3587 32 : if (IsInt32Double(double_res)) {
3588 22 : return H_CONSTANT_INT(double_res);
3589 : }
3590 10 : return H_CONSTANT_DOUBLE(double_res);
3591 54 : } else if (c_left->DoubleValue() != 0) {
3592 : int sign = Double(c_left->DoubleValue()).Sign() *
3593 42 : Double(c_right->DoubleValue()).Sign(); // Right could be -0.
3594 42 : return H_CONSTANT_DOUBLE(sign * V8_INFINITY);
3595 : } else {
3596 12 : return H_CONSTANT_DOUBLE(std::numeric_limits<double>::quiet_NaN());
3597 : }
3598 : }
3599 : }
3600 52355 : return new (zone) HDiv(context, left, right);
3601 : }
3602 :
3603 139726 : HInstruction* HBitwise::New(Isolate* isolate, Zone* zone, HValue* context,
3604 : Token::Value op, HValue* left, HValue* right) {
3605 139806 : if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3606 0 : HConstant* c_left = HConstant::cast(left);
3607 0 : HConstant* c_right = HConstant::cast(right);
3608 0 : if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
3609 : int32_t result;
3610 : int32_t v_left = c_left->NumberValueAsInteger32();
3611 : int32_t v_right = c_right->NumberValueAsInteger32();
3612 0 : switch (op) {
3613 : case Token::BIT_XOR:
3614 0 : result = v_left ^ v_right;
3615 0 : break;
3616 : case Token::BIT_AND:
3617 0 : result = v_left & v_right;
3618 0 : break;
3619 : case Token::BIT_OR:
3620 0 : result = v_left | v_right;
3621 0 : break;
3622 : default:
3623 : result = 0; // Please the compiler.
3624 0 : UNREACHABLE();
3625 : }
3626 0 : return H_CONSTANT_INT(result);
3627 : }
3628 : }
3629 139726 : return new (zone) HBitwise(context, op, left, right);
3630 : }
3631 :
3632 : #define DEFINE_NEW_H_BITWISE_INSTR(HInstr, result) \
3633 : HInstruction* HInstr::New(Isolate* isolate, Zone* zone, HValue* context, \
3634 : HValue* left, HValue* right) { \
3635 : if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) { \
3636 : HConstant* c_left = HConstant::cast(left); \
3637 : HConstant* c_right = HConstant::cast(right); \
3638 : if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
3639 : return H_CONSTANT_INT(result); \
3640 : } \
3641 : } \
3642 : return new (zone) HInstr(context, left, right); \
3643 : }
3644 :
3645 29281 : DEFINE_NEW_H_BITWISE_INSTR(HSar,
3646 : c_left->NumberValueAsInteger32() >> (c_right->NumberValueAsInteger32() & 0x1f))
3647 33138 : DEFINE_NEW_H_BITWISE_INSTR(HShl,
3648 : c_left->NumberValueAsInteger32() << (c_right->NumberValueAsInteger32() & 0x1f))
3649 :
3650 : #undef DEFINE_NEW_H_BITWISE_INSTR
3651 :
3652 9359 : HInstruction* HShr::New(Isolate* isolate, Zone* zone, HValue* context,
3653 : HValue* left, HValue* right) {
3654 9363 : if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3655 0 : HConstant* c_left = HConstant::cast(left);
3656 0 : HConstant* c_right = HConstant::cast(right);
3657 0 : if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
3658 : int32_t left_val = c_left->NumberValueAsInteger32();
3659 0 : int32_t right_val = c_right->NumberValueAsInteger32() & 0x1f;
3660 0 : if ((right_val == 0) && (left_val < 0)) {
3661 0 : return H_CONSTANT_DOUBLE(static_cast<uint32_t>(left_val));
3662 : }
3663 0 : return H_CONSTANT_INT(static_cast<uint32_t>(left_val) >> right_val);
3664 : }
3665 : }
3666 9359 : return new (zone) HShr(context, left, right);
3667 : }
3668 :
3669 :
3670 14320 : HInstruction* HSeqStringGetChar::New(Isolate* isolate, Zone* zone,
3671 : HValue* context, String::Encoding encoding,
3672 : HValue* string, HValue* index) {
3673 14336 : if (FLAG_fold_constants && string->IsConstant() && index->IsConstant()) {
3674 : HConstant* c_string = HConstant::cast(string);
3675 0 : HConstant* c_index = HConstant::cast(index);
3676 0 : if (c_string->HasStringValue() && c_index->HasInteger32Value()) {
3677 : Handle<String> s = c_string->StringValue();
3678 : int32_t i = c_index->Integer32Value();
3679 : DCHECK_LE(0, i);
3680 : DCHECK_LT(i, s->length());
3681 0 : return H_CONSTANT_INT(s->Get(i));
3682 : }
3683 : }
3684 14320 : return new(zone) HSeqStringGetChar(encoding, string, index);
3685 : }
3686 :
3687 :
3688 : #undef H_CONSTANT_INT
3689 : #undef H_CONSTANT_DOUBLE
3690 :
3691 :
3692 0 : std::ostream& HBitwise::PrintDataTo(std::ostream& os) const { // NOLINT
3693 0 : os << Token::Name(op_) << " ";
3694 0 : return HBitwiseBinaryOperation::PrintDataTo(os);
3695 : }
3696 :
3697 :
3698 316825 : void HPhi::SimplifyConstantInputs() {
3699 : // Convert constant inputs to integers when all uses are truncating.
3700 : // This must happen before representation inference takes place.
3701 321605 : if (!CheckUsesForFlag(kTruncatingToInt32)) return;
3702 82233 : for (int i = 0; i < OperandCount(); ++i) {
3703 60180 : if (!OperandAt(i)->IsConstant()) return;
3704 : }
3705 2396 : HGraph* graph = block()->graph();
3706 14350 : for (int i = 0; i < OperandCount(); ++i) {
3707 4791 : HConstant* operand = HConstant::cast(OperandAt(i));
3708 4785 : if (operand->HasInteger32Value()) {
3709 : continue;
3710 3516 : } else if (operand->HasDoubleValue()) {
3711 : HConstant* integer_input = HConstant::New(
3712 6 : graph->isolate(), graph->zone(), graph->GetInvalidContext(),
3713 12 : DoubleToInt32(operand->DoubleValue()));
3714 6 : integer_input->InsertAfter(operand);
3715 6 : SetOperandAt(i, integer_input);
3716 3510 : } else if (operand->HasBooleanValue()) {
3717 : SetOperandAt(i, operand->BooleanValue() ? graph->GetConstant1()
3718 569 : : graph->GetConstant0());
3719 2941 : } else if (operand->ImmortalImmovable()) {
3720 2730 : SetOperandAt(i, graph->GetConstant0());
3721 : }
3722 : }
3723 : // Overwrite observed input representations because they are likely Tagged.
3724 363 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
3725 363 : HValue* use = it.value();
3726 363 : if (use->IsBinaryOperation()) {
3727 : HBinaryOperation::cast(use)->set_observed_input_representation(
3728 253 : it.index(), Representation::Smi());
3729 : }
3730 : }
3731 : }
3732 :
3733 :
3734 475831 : void HPhi::InferRepresentation(HInferRepresentationPhase* h_infer) {
3735 : DCHECK(CheckFlag(kFlexibleRepresentation));
3736 475831 : Representation new_rep = RepresentationFromUses();
3737 475831 : UpdateRepresentation(new_rep, h_infer, "uses");
3738 475830 : new_rep = RepresentationFromInputs();
3739 475828 : UpdateRepresentation(new_rep, h_infer, "inputs");
3740 475833 : new_rep = RepresentationFromUseRequirements();
3741 475828 : UpdateRepresentation(new_rep, h_infer, "use requirements");
3742 475833 : }
3743 :
3744 :
3745 2610794 : Representation HPhi::RepresentationFromInputs() {
3746 475826 : Representation r = representation();
3747 5221590 : for (int i = 0; i < OperandCount(); ++i) {
3748 : // Ignore conservative Tagged assumption of parameters if we have
3749 : // reason to believe that it's too conservative.
3750 2366632 : if (has_type_feedback_from_uses() && OperandAt(i)->IsParameter()) {
3751 : continue;
3752 : }
3753 :
3754 2133308 : r = r.generalize(OperandAt(i)->KnownOptimalRepresentation());
3755 : }
3756 475827 : return r;
3757 : }
3758 :
3759 :
3760 : // Returns a representation if all uses agree on the same representation.
3761 : // Integer32 is also returned when some uses are Smi but others are Integer32.
3762 951664 : Representation HValue::RepresentationFromUseRequirements() {
3763 475832 : Representation rep = Representation::None();
3764 1167419 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
3765 : // Ignore the use requirement from never run code
3766 2403748 : if (it.value()->block()->IsUnreachable()) continue;
3767 :
3768 : // We check for observed_input_representation elsewhere.
3769 : Representation use_rep =
3770 1057819 : it.value()->RequiredInputRepresentation(it.index());
3771 1057842 : if (rep.IsNone()) {
3772 539130 : rep = use_rep;
3773 539130 : continue;
3774 : }
3775 518712 : if (use_rep.IsNone() || rep.Equals(use_rep)) continue;
3776 74568 : if (rep.generalize(use_rep).IsInteger32()) {
3777 2806 : rep = Representation::Integer32();
3778 2806 : continue;
3779 : }
3780 : return Representation::None();
3781 : }
3782 441351 : return rep;
3783 : }
3784 :
3785 :
3786 95617 : bool HValue::HasNonSmiUse() {
3787 17429 : for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
3788 : // We check for observed_input_representation elsewhere.
3789 : Representation use_rep =
3790 108134 : it.value()->RequiredInputRepresentation(it.index());
3791 206750 : if (!use_rep.IsNone() &&
3792 203255 : !use_rep.IsSmi() &&
3793 : !use_rep.IsTagged()) {
3794 : return true;
3795 : }
3796 : }
3797 4912 : return false;
3798 : }
3799 :
3800 :
3801 : // Node-specific verification code is only included in debug mode.
3802 : #ifdef DEBUG
3803 :
3804 : void HPhi::Verify() {
3805 : DCHECK(OperandCount() == block()->predecessors()->length());
3806 : for (int i = 0; i < OperandCount(); ++i) {
3807 : HValue* value = OperandAt(i);
3808 : HBasicBlock* defining_block = value->block();
3809 : HBasicBlock* predecessor_block = block()->predecessors()->at(i);
3810 : DCHECK(defining_block == predecessor_block ||
3811 : defining_block->Dominates(predecessor_block));
3812 : }
3813 : }
3814 :
3815 :
3816 : void HSimulate::Verify() {
3817 : HInstruction::Verify();
3818 : DCHECK(HasAstId() || next()->IsEnterInlined());
3819 : }
3820 :
3821 :
3822 : void HCheckHeapObject::Verify() {
3823 : HInstruction::Verify();
3824 : DCHECK(HasNoUses());
3825 : }
3826 :
3827 :
3828 : void HCheckValue::Verify() {
3829 : HInstruction::Verify();
3830 : DCHECK(HasNoUses());
3831 : }
3832 :
3833 : #endif
3834 :
3835 :
3836 0 : HObjectAccess HObjectAccess::ForFixedArrayHeader(int offset) {
3837 : DCHECK(offset >= 0);
3838 : DCHECK(offset < FixedArray::kHeaderSize);
3839 0 : if (offset == FixedArray::kLengthOffset) return ForFixedArrayLength();
3840 0 : return HObjectAccess(kInobject, offset);
3841 : }
3842 :
3843 :
3844 57349 : HObjectAccess HObjectAccess::ForMapAndOffset(Handle<Map> map, int offset,
3845 : Representation representation) {
3846 : DCHECK(offset >= 0);
3847 : Portion portion = kInobject;
3848 :
3849 57349 : if (offset == JSObject::kElementsOffset) {
3850 : portion = kElementsPointer;
3851 52750 : } else if (offset == JSObject::kMapOffset) {
3852 : portion = kMaps;
3853 : }
3854 : bool existing_inobject_property = true;
3855 57349 : if (!map.is_null()) {
3856 : existing_inobject_property = (offset <
3857 50985 : map->instance_size() - map->unused_property_fields() * kPointerSize);
3858 : }
3859 : return HObjectAccess(portion, offset, representation, Handle<String>::null(),
3860 57349 : false, existing_inobject_property);
3861 : }
3862 :
3863 :
3864 14320 : HObjectAccess HObjectAccess::ForAllocationSiteOffset(int offset) {
3865 14320 : switch (offset) {
3866 : case AllocationSite::kTransitionInfoOffset:
3867 0 : return HObjectAccess(kInobject, offset, Representation::Tagged());
3868 : case AllocationSite::kNestedSiteOffset:
3869 0 : return HObjectAccess(kInobject, offset, Representation::Tagged());
3870 : case AllocationSite::kPretenureDataOffset:
3871 0 : return HObjectAccess(kInobject, offset, Representation::Smi());
3872 : case AllocationSite::kPretenureCreateCountOffset:
3873 14320 : return HObjectAccess(kInobject, offset, Representation::Smi());
3874 : case AllocationSite::kDependentCodeOffset:
3875 0 : return HObjectAccess(kInobject, offset, Representation::Tagged());
3876 : case AllocationSite::kWeakNextOffset:
3877 0 : return HObjectAccess(kInobject, offset, Representation::Tagged());
3878 : default:
3879 0 : UNREACHABLE();
3880 : }
3881 : return HObjectAccess(kInobject, offset);
3882 : }
3883 :
3884 :
3885 32540 : HObjectAccess HObjectAccess::ForContextSlot(int index) {
3886 : DCHECK(index >= 0);
3887 : Portion portion = kInobject;
3888 32540 : int offset = Context::kHeaderSize + index * kPointerSize;
3889 : DCHECK_EQ(offset, Context::SlotOffset(index) + kHeapObjectTag);
3890 32540 : return HObjectAccess(portion, offset, Representation::Tagged());
3891 : }
3892 :
3893 :
3894 0 : HObjectAccess HObjectAccess::ForScriptContext(int index) {
3895 : DCHECK(index >= 0);
3896 : Portion portion = kInobject;
3897 : int offset = ScriptContextTable::GetContextOffset(index);
3898 0 : return HObjectAccess(portion, offset, Representation::Tagged());
3899 : }
3900 :
3901 :
3902 0 : HObjectAccess HObjectAccess::ForJSArrayOffset(int offset) {
3903 : DCHECK(offset >= 0);
3904 : Portion portion = kInobject;
3905 :
3906 0 : if (offset == JSObject::kElementsOffset) {
3907 : portion = kElementsPointer;
3908 0 : } else if (offset == JSArray::kLengthOffset) {
3909 : portion = kArrayLengths;
3910 0 : } else if (offset == JSObject::kMapOffset) {
3911 : portion = kMaps;
3912 : }
3913 0 : return HObjectAccess(portion, offset);
3914 : }
3915 :
3916 :
3917 0 : HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset,
3918 : Representation representation) {
3919 : DCHECK(offset >= 0);
3920 : return HObjectAccess(kBackingStore, offset, representation,
3921 0 : Handle<String>::null(), false, false);
3922 : }
3923 :
3924 :
3925 112843 : HObjectAccess HObjectAccess::ForField(Handle<Map> map, int index,
3926 : Representation representation,
3927 : Handle<Name> name) {
3928 112843 : if (index < 0) {
3929 : // Negative property indices are in-object properties, indexed
3930 : // from the end of the fixed part of the object.
3931 213476 : int offset = (index * kPointerSize) + map->instance_size();
3932 106738 : return HObjectAccess(kInobject, offset, representation, name, false, true);
3933 : } else {
3934 : // Non-negative property indices are in the properties array.
3935 6105 : int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
3936 : return HObjectAccess(kBackingStore, offset, representation, name,
3937 6105 : false, false);
3938 : }
3939 : }
3940 :
3941 :
3942 1138666 : void HObjectAccess::SetGVNFlags(HValue *instr, PropertyAccessType access_type) {
3943 : // set the appropriate GVN flags for a given load or store instruction
3944 569333 : if (access_type == STORE) {
3945 : // track dominating allocations in order to eliminate write barriers
3946 : instr->SetDependsOnFlag(::v8::internal::kNewSpacePromotion);
3947 : instr->SetFlag(HValue::kTrackSideEffectDominators);
3948 : } else {
3949 : // try to GVN loads, but don't hoist above map changes
3950 : instr->SetFlag(HValue::kUseGVN);
3951 : instr->SetDependsOnFlag(::v8::internal::kMaps);
3952 : }
3953 :
3954 569333 : switch (portion()) {
3955 : case kArrayLengths:
3956 59357 : if (access_type == STORE) {
3957 : instr->SetChangesFlag(::v8::internal::kArrayLengths);
3958 : } else {
3959 : instr->SetDependsOnFlag(::v8::internal::kArrayLengths);
3960 : }
3961 : break;
3962 : case kStringLengths:
3963 62484 : if (access_type == STORE) {
3964 : instr->SetChangesFlag(::v8::internal::kStringLengths);
3965 : } else {
3966 : instr->SetDependsOnFlag(::v8::internal::kStringLengths);
3967 : }
3968 : break;
3969 : case kInobject:
3970 292079 : if (access_type == STORE) {
3971 : instr->SetChangesFlag(::v8::internal::kInobjectFields);
3972 : } else {
3973 : instr->SetDependsOnFlag(::v8::internal::kInobjectFields);
3974 : }
3975 : break;
3976 : case kDouble:
3977 2221 : if (access_type == STORE) {
3978 : instr->SetChangesFlag(::v8::internal::kDoubleFields);
3979 : } else {
3980 : instr->SetDependsOnFlag(::v8::internal::kDoubleFields);
3981 : }
3982 : break;
3983 : case kBackingStore:
3984 3651 : if (access_type == STORE) {
3985 : instr->SetChangesFlag(::v8::internal::kBackingStoreFields);
3986 : } else {
3987 : instr->SetDependsOnFlag(::v8::internal::kBackingStoreFields);
3988 : }
3989 : break;
3990 : case kElementsPointer:
3991 65142 : if (access_type == STORE) {
3992 : instr->SetChangesFlag(::v8::internal::kElementsPointer);
3993 : } else {
3994 : instr->SetDependsOnFlag(::v8::internal::kElementsPointer);
3995 : }
3996 : break;
3997 : case kMaps:
3998 84399 : if (access_type == STORE) {
3999 : instr->SetChangesFlag(::v8::internal::kMaps);
4000 : } else {
4001 : instr->SetDependsOnFlag(::v8::internal::kMaps);
4002 : }
4003 : break;
4004 : case kExternalMemory:
4005 0 : if (access_type == STORE) {
4006 : instr->SetChangesFlag(::v8::internal::kExternalMemory);
4007 : } else {
4008 : instr->SetDependsOnFlag(::v8::internal::kExternalMemory);
4009 : }
4010 : break;
4011 : }
4012 569333 : }
4013 :
4014 :
4015 0 : std::ostream& operator<<(std::ostream& os, const HObjectAccess& access) {
4016 0 : os << ".";
4017 :
4018 0 : switch (access.portion()) {
4019 : case HObjectAccess::kArrayLengths:
4020 : case HObjectAccess::kStringLengths:
4021 0 : os << "%length";
4022 0 : break;
4023 : case HObjectAccess::kElementsPointer:
4024 0 : os << "%elements";
4025 0 : break;
4026 : case HObjectAccess::kMaps:
4027 0 : os << "%map";
4028 0 : break;
4029 : case HObjectAccess::kDouble: // fall through
4030 : case HObjectAccess::kInobject:
4031 0 : if (!access.name().is_null() && access.name()->IsString()) {
4032 0 : os << Handle<String>::cast(access.name())->ToCString().get();
4033 : }
4034 0 : os << "[in-object]";
4035 0 : break;
4036 : case HObjectAccess::kBackingStore:
4037 0 : if (!access.name().is_null() && access.name()->IsString()) {
4038 0 : os << Handle<String>::cast(access.name())->ToCString().get();
4039 : }
4040 0 : os << "[backing-store]";
4041 0 : break;
4042 : case HObjectAccess::kExternalMemory:
4043 0 : os << "[external-memory]";
4044 0 : break;
4045 : }
4046 :
4047 0 : return os << "@" << access.offset();
4048 : }
4049 :
4050 : } // namespace internal
4051 : } // namespace v8
|