Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(403)

Side by Side Diff: src/hydrogen-instructions.cc

Issue 6529055: [Isolates] Merge crankshaft (r5922 from bleeding_edge). (Closed)
Patch Set: Win32 port Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/assembler-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "v8.h"
29
30 #include "factory.h"
31 #include "hydrogen.h"
32
33 #if V8_TARGET_ARCH_IA32
34 #include "ia32/lithium-ia32.h"
35 #elif V8_TARGET_ARCH_X64
36 #include "x64/lithium-x64.h"
37 #elif V8_TARGET_ARCH_ARM
38 #include "arm/lithium-arm.h"
39 #else
40 #error Unsupported target architecture.
41 #endif
42
43 namespace v8 {
44 namespace internal {
45
46 #define DEFINE_COMPILE(type) \
47 LInstruction* H##type::CompileToLithium(LChunkBuilder* builder) { \
48 return builder->Do##type(this); \
49 }
50 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
51 #undef DEFINE_COMPILE
52
53
54 const char* Representation::Mnemonic() const {
55 switch (kind_) {
56 case kNone: return "v";
57 case kTagged: return "t";
58 case kDouble: return "d";
59 case kInteger32: return "i";
60 default:
61 UNREACHABLE();
62 return NULL;
63 }
64 }
65
66
67 static int32_t AddAssertNoOverflow(int32_t a, int32_t b) {
68 ASSERT(static_cast<int64_t>(a + b) == (static_cast<int64_t>(a) +
69 static_cast<int64_t>(b)));
70 return a + b;
71 }
72
73
74 static int32_t SubAssertNoOverflow(int32_t a, int32_t b) {
75 ASSERT(static_cast<int64_t>(a - b) == (static_cast<int64_t>(a) -
76 static_cast<int64_t>(b)));
77 return a - b;
78 }
79
80
81 static int32_t MulAssertNoOverflow(int32_t a, int32_t b) {
82 ASSERT(static_cast<int64_t>(a * b) == (static_cast<int64_t>(a) *
83 static_cast<int64_t>(b)));
84 return a * b;
85 }
86
87
88 static int32_t AddWithoutOverflow(int32_t a, int32_t b) {
89 if (b > 0) {
90 if (a <= kMaxInt - b) return AddAssertNoOverflow(a, b);
91 return kMaxInt;
92 } else {
93 if (a >= kMinInt - b) return AddAssertNoOverflow(a, b);
94 return kMinInt;
95 }
96 }
97
98
99 static int32_t SubWithoutOverflow(int32_t a, int32_t b) {
100 if (b < 0) {
101 if (a <= kMaxInt + b) return SubAssertNoOverflow(a, b);
102 return kMaxInt;
103 } else {
104 if (a >= kMinInt + b) return SubAssertNoOverflow(a, b);
105 return kMinInt;
106 }
107 }
108
109
110 static int32_t MulWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
111 if (b == 0 || a == 0) return 0;
112 if (a == 1) return b;
113 if (b == 1) return a;
114
115 int sign = 1;
116 if ((a < 0 && b > 0) || (a > 0 && b < 0)) sign = -1;
117 if (a < 0) a = -a;
118 if (b < 0) b = -b;
119
120 if (kMaxInt / b > a && a != kMinInt && b != kMinInt) {
121 return MulAssertNoOverflow(a, b) * sign;
122 }
123
124 *overflow = true;
125 if (sign == 1) {
126 return kMaxInt;
127 } else {
128 return kMinInt;
129 }
130 }
131
132
133 int32_t Range::Mask() const {
134 if (lower_ == upper_) return lower_;
135 if (lower_ >= 0) {
136 int32_t res = 1;
137 while (res < upper_) {
138 res = (res << 1) | 1;
139 }
140 return res;
141 }
142 return 0xffffffff;
143 }
144
145
146 void Range::Add(int32_t value) {
147 if (value == 0) return;
148 lower_ = AddWithoutOverflow(lower_, value);
149 upper_ = AddWithoutOverflow(upper_, value);
150 Verify();
151 }
152
153
154 // Returns whether the add may overflow.
155 bool Range::AddAndCheckOverflow(Range* other) {
156 int old_lower = lower_;
157 int old_upper = upper_;
158 lower_ = AddWithoutOverflow(lower_, other->lower());
159 upper_ = AddWithoutOverflow(upper_, other->upper());
160 bool r = (old_lower + other->lower() != lower_ ||
161 old_upper + other->upper() != upper_);
162 KeepOrder();
163 Verify();
164 return r;
165 }
166
167
168 // Returns whether the sub may overflow.
169 bool Range::SubAndCheckOverflow(Range* other) {
170 int old_lower = lower_;
171 int old_upper = upper_;
172 lower_ = SubWithoutOverflow(lower_, other->lower());
173 upper_ = SubWithoutOverflow(upper_, other->upper());
174 bool r = (old_lower - other->lower() != lower_ ||
175 old_upper - other->upper() != upper_);
176 KeepOrder();
177 Verify();
178 return r;
179 }
180
181
182 void Range::KeepOrder() {
183 if (lower_ > upper_) {
184 int32_t tmp = lower_;
185 lower_ = upper_;
186 upper_ = tmp;
187 }
188 }
189
190
191 void Range::Verify() const {
192 ASSERT(lower_ <= upper_);
193 }
194
195
196 // Returns whether the mul may overflow.
197 bool Range::MulAndCheckOverflow(Range* other) {
198 bool may_overflow = false;
199 int v1 = MulWithoutOverflow(lower_, other->lower(), &may_overflow);
200 int v2 = MulWithoutOverflow(lower_, other->upper(), &may_overflow);
201 int v3 = MulWithoutOverflow(upper_, other->lower(), &may_overflow);
202 int v4 = MulWithoutOverflow(upper_, other->upper(), &may_overflow);
203 lower_ = Min(Min(v1, v2), Min(v3, v4));
204 upper_ = Max(Max(v1, v2), Max(v3, v4));
205 Verify();
206 return may_overflow;
207 }
208
209
210 const char* HType::ToString() {
211 switch (type_) {
212 case kTagged: return "tagged";
213 case kTaggedPrimitive: return "primitive";
214 case kTaggedNumber: return "number";
215 case kSmi: return "smi";
216 case kHeapNumber: return "heap-number";
217 case kString: return "string";
218 case kBoolean: return "boolean";
219 case kNonPrimitive: return "non-primitive";
220 case kJSArray: return "array";
221 case kJSObject: return "object";
222 case kUninitialized: return "uninitialized";
223 }
224 UNREACHABLE();
225 return "Unreachable code";
226 }
227
228
229 const char* HType::ToShortString() {
230 switch (type_) {
231 case kTagged: return "t";
232 case kTaggedPrimitive: return "p";
233 case kTaggedNumber: return "n";
234 case kSmi: return "m";
235 case kHeapNumber: return "h";
236 case kString: return "s";
237 case kBoolean: return "b";
238 case kNonPrimitive: return "r";
239 case kJSArray: return "a";
240 case kJSObject: return "o";
241 case kUninitialized: return "z";
242 }
243 UNREACHABLE();
244 return "Unreachable code";
245 }
246
247
248 HType HType::TypeFromValue(Handle<Object> value) {
249 HType result = HType::Tagged();
250 if (value->IsSmi()) {
251 result = HType::Smi();
252 } else if (value->IsHeapNumber()) {
253 result = HType::HeapNumber();
254 } else if (value->IsString()) {
255 result = HType::String();
256 } else if (value->IsBoolean()) {
257 result = HType::Boolean();
258 } else if (value->IsJSObject()) {
259 result = HType::JSObject();
260 } else if (value->IsJSArray()) {
261 result = HType::JSArray();
262 }
263 return result;
264 }
265
266
267 int HValue::LookupOperandIndex(int occurrence_index, HValue* op) const {
268 for (int i = 0; i < OperandCount(); ++i) {
269 if (OperandAt(i) == op) {
270 if (occurrence_index == 0) return i;
271 --occurrence_index;
272 }
273 }
274 return -1;
275 }
276
277
278 bool HValue::IsDefinedAfter(HBasicBlock* other) const {
279 return block()->block_id() > other->block_id();
280 }
281
282
283 bool HValue::UsesMultipleTimes(HValue* op) const {
284 bool seen = false;
285 for (int i = 0; i < OperandCount(); ++i) {
286 if (OperandAt(i) == op) {
287 if (seen) return true;
288 seen = true;
289 }
290 }
291 return false;
292 }
293
294
295 bool HValue::Equals(HValue* other) const {
296 if (other->opcode() != opcode()) return false;
297 if (!other->representation().Equals(representation())) return false;
298 if (!other->type_.Equals(type_)) return false;
299 if (OperandCount() != other->OperandCount()) return false;
300 for (int i = 0; i < OperandCount(); ++i) {
301 if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false;
302 }
303 bool result = DataEquals(other);
304 ASSERT(!result || Hashcode() == other->Hashcode());
305 return result;
306 }
307
308
309 intptr_t HValue::Hashcode() const {
310 intptr_t result = opcode();
311 int count = OperandCount();
312 for (int i = 0; i < count; ++i) {
313 result = result * 19 + OperandAt(i)->id() + (result >> 7);
314 }
315 return result;
316 }
317
318
319 void HValue::SetOperandAt(int index, HValue* value) {
320 ASSERT(value == NULL || !value->representation().IsNone());
321 RegisterUse(index, value);
322 InternalSetOperandAt(index, value);
323 }
324
325
326 void HValue::ReplaceAndDelete(HValue* other) {
327 ReplaceValue(other);
328 Delete();
329 }
330
331
332 void HValue::ReplaceValue(HValue* other) {
333 ZoneList<HValue*> start_uses(2);
334 for (int i = 0; i < uses_.length(); ++i) {
335 HValue* use = uses_.at(i);
336 if (!use->block()->IsStartBlock()) {
337 InternalReplaceAtUse(use, other);
338 other->uses_.Add(use);
339 } else {
340 start_uses.Add(use);
341 }
342 }
343 uses_.Clear();
344 uses_.AddAll(start_uses);
345 }
346
347
348 void HValue::ClearOperands() {
349 for (int i = 0; i < OperandCount(); ++i) {
350 SetOperandAt(i, NULL);
351 }
352 }
353
354
355 void HValue::Delete() {
356 ASSERT(HasNoUses());
357 ClearOperands();
358 DeleteFromGraph();
359 }
360
361
362 void HValue::ReplaceAtUse(HValue* use, HValue* other) {
363 for (int i = 0; i < use->OperandCount(); ++i) {
364 if (use->OperandAt(i) == this) {
365 use->SetOperandAt(i, other);
366 }
367 }
368 }
369
370
371 void HValue::ReplaceFirstAtUse(HValue* use, HValue* other, Representation r) {
372 for (int i = 0; i < use->OperandCount(); ++i) {
373 if (use->RequiredInputRepresentation(i).Equals(r) &&
374 use->OperandAt(i) == this) {
375 use->SetOperandAt(i, other);
376 return;
377 }
378 }
379 }
380
381
382 void HValue::InternalReplaceAtUse(HValue* use, HValue* other) {
383 for (int i = 0; i < use->OperandCount(); ++i) {
384 if (use->OperandAt(i) == this) {
385 // Call internal method that does not update use lists. The caller is
386 // responsible for doing so.
387 use->InternalSetOperandAt(i, other);
388 }
389 }
390 }
391
392
393 void HValue::SetBlock(HBasicBlock* block) {
394 ASSERT(block_ == NULL || block == NULL);
395 block_ = block;
396 if (id_ == kNoNumber && block != NULL) {
397 id_ = block->graph()->GetNextValueID(this);
398 }
399 }
400
401
402 void HValue::PrintTypeTo(HType type, StringStream* stream) {
403 stream->Add(type.ToShortString());
404 }
405
406
407 void HValue::PrintNameTo(StringStream* stream) {
408 stream->Add("%s%d", representation_.Mnemonic(), id());
409 }
410
411
412 bool HValue::UpdateInferredType() {
413 HType type = CalculateInferredType();
414 bool result = (!type.Equals(type_));
415 type_ = type;
416 return result;
417 }
418
419
420 void HValue::RegisterUse(int index, HValue* new_value) {
421 HValue* old_value = OperandAt(index);
422 if (old_value == new_value) return;
423 if (old_value != NULL) {
424 ASSERT(old_value->uses_.Contains(this));
425 old_value->uses_.RemoveElement(this);
426 }
427 if (new_value != NULL) {
428 new_value->uses_.Add(this);
429 }
430 }
431
432
433 void HValue::AddNewRange(Range* r) {
434 if (!HasRange()) ComputeInitialRange();
435 if (!HasRange()) range_ = new Range();
436 ASSERT(HasRange());
437 r->StackUpon(range_);
438 range_ = r;
439 }
440
441
442 void HValue::RemoveLastAddedRange() {
443 ASSERT(HasRange());
444 ASSERT(range_->next() != NULL);
445 range_ = range_->next();
446 }
447
448
449 void HValue::ComputeInitialRange() {
450 ASSERT(!HasRange());
451 range_ = InferRange();
452 ASSERT(HasRange());
453 }
454
455
456 void HInstruction::PrintTo(StringStream* stream) const {
457 stream->Add("%s", Mnemonic());
458 if (HasSideEffects()) stream->Add("*");
459 stream->Add(" ");
460 PrintDataTo(stream);
461
462 if (range() != NULL) {
463 stream->Add(" range[%d,%d,m0=%d]",
464 range()->lower(),
465 range()->upper(),
466 static_cast<int>(range()->CanBeMinusZero()));
467 }
468
469 int changes_flags = (flags() & HValue::ChangesFlagsMask());
470 if (changes_flags != 0) {
471 stream->Add(" changes[0x%x]", changes_flags);
472 }
473
474 if (representation().IsTagged() && !type().Equals(HType::Tagged())) {
475 stream->Add(" type[%s]", type().ToString());
476 }
477 }
478
479
480 void HInstruction::Unlink() {
481 ASSERT(IsLinked());
482 ASSERT(!IsControlInstruction()); // Must never move control instructions.
483 clear_block();
484 if (previous_ != NULL) previous_->next_ = next_;
485 if (next_ != NULL) next_->previous_ = previous_;
486 }
487
488
489 void HInstruction::InsertBefore(HInstruction* next) {
490 ASSERT(!IsLinked());
491 ASSERT(!next->IsBlockEntry());
492 ASSERT(!IsControlInstruction());
493 ASSERT(!next->block()->IsStartBlock());
494 ASSERT(next->previous_ != NULL);
495 HInstruction* prev = next->previous();
496 prev->next_ = this;
497 next->previous_ = this;
498 next_ = next;
499 previous_ = prev;
500 SetBlock(next->block());
501 }
502
503
504 void HInstruction::InsertAfter(HInstruction* previous) {
505 ASSERT(!IsLinked());
506 ASSERT(!previous->IsControlInstruction());
507 ASSERT(!IsControlInstruction() || previous->next_ == NULL);
508 HBasicBlock* block = previous->block();
509 // Never insert anything except constants into the start block after finishing
510 // it.
511 if (block->IsStartBlock() && block->IsFinished() && !IsConstant()) {
512 ASSERT(block->end()->SecondSuccessor() == NULL);
513 InsertAfter(block->end()->FirstSuccessor()->first());
514 return;
515 }
516
517 // If we're inserting after an instruction with side-effects that is
518 // followed by a simulate instruction, we need to insert after the
519 // simulate instruction instead.
520 HInstruction* next = previous->next_;
521 if (previous->HasSideEffects() && next != NULL) {
522 ASSERT(next->IsSimulate());
523 previous = next;
524 next = previous->next_;
525 }
526
527 previous_ = previous;
528 next_ = next;
529 SetBlock(block);
530 previous->next_ = this;
531 if (next != NULL) next->previous_ = this;
532 }
533
534
535 #ifdef DEBUG
536 void HInstruction::Verify() const {
537 // Verify that input operands are defined before use.
538 HBasicBlock* cur_block = block();
539 for (int i = 0; i < OperandCount(); ++i) {
540 HValue* other_operand = OperandAt(i);
541 HBasicBlock* other_block = other_operand->block();
542 if (cur_block == other_block) {
543 if (!other_operand->IsPhi()) {
544 HInstruction* cur = cur_block->first();
545 while (cur != NULL) {
546 ASSERT(cur != this); // We should reach other_operand before!
547 if (cur == other_operand) break;
548 cur = cur->next();
549 }
550 // Must reach other operand in the same block!
551 ASSERT(cur == other_operand);
552 }
553 } else {
554 ASSERT(other_block->Dominates(cur_block));
555 }
556 }
557
558 // Verify that instructions that may have side-effects are followed
559 // by a simulate instruction.
560 if (HasSideEffects() && !IsOsrEntry()) {
561 ASSERT(next()->IsSimulate());
562 }
563 }
564 #endif
565
566
567 HCall::HCall(int count) : arguments_(ZONE->NewArray<HValue*>(count), count) {
568 for (int i = 0; i < count; ++i) arguments_[i] = NULL;
569 set_representation(Representation::Tagged());
570 SetFlagMask(AllSideEffects());
571 }
572
573
574 void HCall::PrintDataTo(StringStream* stream) const {
575 stream->Add("(");
576 for (int i = 0; i < arguments_.length(); ++i) {
577 if (i != 0) stream->Add(", ");
578 arguments_.at(i)->PrintNameTo(stream);
579 }
580 stream->Add(")");
581 }
582
583
584 void HClassOfTest::PrintDataTo(StringStream* stream) const {
585 stream->Add("class_of_test(");
586 value()->PrintTo(stream);
587 stream->Add(", \"%o\")", *class_name());
588 }
589
590
591 void HAccessArgumentsAt::PrintDataTo(StringStream* stream) const {
592 arguments()->PrintNameTo(stream);
593 stream->Add("[");
594 index()->PrintNameTo(stream);
595 stream->Add("], length ");
596 length()->PrintNameTo(stream);
597 }
598
599
600 void HCall::SetArgumentAt(int index, HPushArgument* push_argument) {
601 push_argument->set_argument_index(index);
602 SetOperandAt(index, push_argument);
603 }
604
605
606 void HCallConstantFunction::PrintDataTo(StringStream* stream) const {
607 if (IsApplyFunction()) {
608 stream->Add("SPECIAL function: apply");
609 } else {
610 stream->Add("%s", *(function()->shared()->DebugName()->ToCString()));
611 }
612 HCall::PrintDataTo(stream);
613 }
614
615
616 void HBranch::PrintDataTo(StringStream* stream) const {
617 int first_id = FirstSuccessor()->block_id();
618 int second_id = SecondSuccessor()->block_id();
619 stream->Add("on ");
620 value()->PrintNameTo(stream);
621 stream->Add(" (B%d, B%d)", first_id, second_id);
622 }
623
624
625 void HGoto::PrintDataTo(StringStream* stream) const {
626 stream->Add("B%d", FirstSuccessor()->block_id());
627 }
628
629
630 void HReturn::PrintDataTo(StringStream* stream) const {
631 value()->PrintNameTo(stream);
632 }
633
634
635 void HThrow::PrintDataTo(StringStream* stream) const {
636 value()->PrintNameTo(stream);
637 }
638
639
640 const char* HUnaryMathOperation::OpName() const {
641 switch (op()) {
642 case kMathFloor: return "floor";
643 case kMathRound: return "round";
644 case kMathCeil: return "ceil";
645 case kMathAbs: return "abs";
646 case kMathLog: return "log";
647 case kMathSin: return "sin";
648 case kMathCos: return "cos";
649 case kMathTan: return "tan";
650 case kMathASin: return "asin";
651 case kMathACos: return "acos";
652 case kMathATan: return "atan";
653 case kMathExp: return "exp";
654 case kMathSqrt: return "sqrt";
655 default: break;
656 }
657 return "(unknown operation)";
658 }
659
660
661 void HUnaryMathOperation::PrintDataTo(StringStream* stream) const {
662 const char* name = OpName();
663 stream->Add("%s ", name);
664 value()->PrintNameTo(stream);
665 }
666
667
668 void HUnaryOperation::PrintDataTo(StringStream* stream) const {
669 value()->PrintNameTo(stream);
670 }
671
672
673 void HHasInstanceType::PrintDataTo(StringStream* stream) const {
674 value()->PrintNameTo(stream);
675 switch (from_) {
676 case FIRST_JS_OBJECT_TYPE:
677 if (to_ == LAST_TYPE) stream->Add(" spec_object");
678 break;
679 case JS_REGEXP_TYPE:
680 if (to_ == JS_REGEXP_TYPE) stream->Add(" reg_exp");
681 break;
682 case JS_ARRAY_TYPE:
683 if (to_ == JS_ARRAY_TYPE) stream->Add(" array");
684 break;
685 case JS_FUNCTION_TYPE:
686 if (to_ == JS_FUNCTION_TYPE) stream->Add(" function");
687 break;
688 default:
689 break;
690 }
691 }
692
693
694 void HTypeofIs::PrintDataTo(StringStream* stream) const {
695 value()->PrintNameTo(stream);
696 stream->Add(" == ");
697 stream->Add(type_literal_->ToAsciiVector());
698 }
699
700
701 void HPushArgument::PrintDataTo(StringStream* stream) const {
702 HUnaryOperation::PrintDataTo(stream);
703 if (argument_index() != -1) {
704 stream->Add(" [%d]", argument_index_);
705 }
706 }
707
708
709 void HChange::PrintDataTo(StringStream* stream) const {
710 HUnaryOperation::PrintDataTo(stream);
711 stream->Add(" %s to %s", from_.Mnemonic(), to_.Mnemonic());
712
713 if (CanTruncateToInt32()) stream->Add(" truncating-int32");
714 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
715 }
716
717
718 HCheckInstanceType* HCheckInstanceType::NewIsJSObjectOrJSFunction(
719 HValue* value) {
720 STATIC_ASSERT((LAST_JS_OBJECT_TYPE + 1) == JS_FUNCTION_TYPE);
721 return new HCheckInstanceType(value, FIRST_JS_OBJECT_TYPE, JS_FUNCTION_TYPE);
722 }
723
724
725 void HCheckMap::PrintDataTo(StringStream* stream) const {
726 value()->PrintNameTo(stream);
727 stream->Add(" %p", *map());
728 }
729
730
731 void HCheckFunction::PrintDataTo(StringStream* stream) const {
732 value()->PrintNameTo(stream);
733 stream->Add(" %p", *target());
734 }
735
736
737 void HCallKeyed::PrintDataTo(StringStream* stream) const {
738 stream->Add("[");
739 key()->PrintNameTo(stream);
740 stream->Add("](");
741 for (int i = 1; i < arguments_.length(); ++i) {
742 if (i != 1) stream->Add(", ");
743 arguments_.at(i)->PrintNameTo(stream);
744 }
745 stream->Add(")");
746 }
747
748
749 void HCallNamed::PrintDataTo(StringStream* stream) const {
750 SmartPointer<char> name_string = name()->ToCString();
751 stream->Add("%s ", *name_string);
752 HCall::PrintDataTo(stream);
753 }
754
755
756 void HCallGlobal::PrintDataTo(StringStream* stream) const {
757 SmartPointer<char> name_string = name()->ToCString();
758 stream->Add("%s ", *name_string);
759 HCall::PrintDataTo(stream);
760 }
761
762
763 void HCallRuntime::PrintDataTo(StringStream* stream) const {
764 SmartPointer<char> name_string = name()->ToCString();
765 stream->Add("%s ", *name_string);
766 HCall::PrintDataTo(stream);
767 }
768
769 void HCallStub::PrintDataTo(StringStream* stream) const {
770 stream->Add("%s(%d)",
771 CodeStub::MajorName(major_key_, false),
772 argument_count_);
773 }
774
775
776 Range* HValue::InferRange() {
777 if (representation().IsTagged()) {
778 // Tagged values are always in int32 range when converted to integer,
779 // but they can contain -0.
780 Range* result = new Range();
781 result->set_can_be_minus_zero(true);
782 return result;
783 } else if (representation().IsNone()) {
784 return NULL;
785 } else {
786 return new Range();
787 }
788 }
789
790
791 Range* HConstant::InferRange() {
792 if (has_int32_value_) {
793 Range* result = new Range(int32_value_, int32_value_);
794 result->set_can_be_minus_zero(false);
795 return result;
796 }
797 return HInstruction::InferRange();
798 }
799
800
801 Range* HPhi::InferRange() {
802 if (representation().IsInteger32()) {
803 if (block()->IsLoopHeader()) {
804 Range* range = new Range(kMinInt, kMaxInt);
805 return range;
806 } else {
807 Range* range = OperandAt(0)->range()->Copy();
808 for (int i = 1; i < OperandCount(); ++i) {
809 range->Union(OperandAt(i)->range());
810 }
811 return range;
812 }
813 } else {
814 return HValue::InferRange();
815 }
816 }
817
818
819 Range* HAdd::InferRange() {
820 if (representation().IsInteger32()) {
821 Range* a = left()->range();
822 Range* b = right()->range();
823 Range* res = a->Copy();
824 if (!res->AddAndCheckOverflow(b)) {
825 ClearFlag(kCanOverflow);
826 }
827 bool m0 = a->CanBeMinusZero() && b->CanBeMinusZero();
828 res->set_can_be_minus_zero(m0);
829 return res;
830 } else {
831 return HArithmeticBinaryOperation::InferRange();
832 }
833 }
834
835
836 Range* HSub::InferRange() {
837 if (representation().IsInteger32()) {
838 Range* a = left()->range();
839 Range* b = right()->range();
840 Range* res = a->Copy();
841 if (!res->SubAndCheckOverflow(b)) {
842 ClearFlag(kCanOverflow);
843 }
844 res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
845 return res;
846 } else {
847 return HArithmeticBinaryOperation::InferRange();
848 }
849 }
850
851
852 Range* HMul::InferRange() {
853 if (representation().IsInteger32()) {
854 Range* a = left()->range();
855 Range* b = right()->range();
856 Range* res = a->Copy();
857 if (!res->MulAndCheckOverflow(b)) {
858 ClearFlag(kCanOverflow);
859 }
860 bool m0 = (a->CanBeZero() && b->CanBeNegative()) ||
861 (a->CanBeNegative() && b->CanBeZero());
862 res->set_can_be_minus_zero(m0);
863 return res;
864 } else {
865 return HArithmeticBinaryOperation::InferRange();
866 }
867 }
868
869
870 Range* HDiv::InferRange() {
871 if (representation().IsInteger32()) {
872 Range* result = new Range();
873 if (left()->range()->CanBeMinusZero()) {
874 result->set_can_be_minus_zero(true);
875 }
876
877 if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) {
878 result->set_can_be_minus_zero(true);
879 }
880
881 if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
882 SetFlag(HValue::kCanOverflow);
883 }
884
885 if (!right()->range()->CanBeZero()) {
886 ClearFlag(HValue::kCanBeDivByZero);
887 }
888 return result;
889 } else {
890 return HArithmeticBinaryOperation::InferRange();
891 }
892 }
893
894
895 Range* HMod::InferRange() {
896 if (representation().IsInteger32()) {
897 Range* a = left()->range();
898 Range* result = new Range();
899 if (a->CanBeMinusZero() || a->CanBeNegative()) {
900 result->set_can_be_minus_zero(true);
901 }
902 if (!right()->range()->CanBeZero()) {
903 ClearFlag(HValue::kCanBeDivByZero);
904 }
905 return result;
906 } else {
907 return HArithmeticBinaryOperation::InferRange();
908 }
909 }
910
911
912 void HPhi::PrintTo(StringStream* stream) const {
913 stream->Add("[");
914 for (int i = 0; i < OperandCount(); ++i) {
915 HValue* value = OperandAt(i);
916 stream->Add(" ");
917 value->PrintNameTo(stream);
918 stream->Add(" ");
919 }
920 stream->Add(" uses%d_%di_%dd_%dt]",
921 uses()->length(),
922 int32_non_phi_uses() + int32_indirect_uses(),
923 double_non_phi_uses() + double_indirect_uses(),
924 tagged_non_phi_uses() + tagged_indirect_uses());
925 }
926
927
928 void HPhi::AddInput(HValue* value) {
929 inputs_.Add(NULL);
930 SetOperandAt(OperandCount() - 1, value);
931 // Mark phis that may have 'arguments' directly or indirectly as an operand.
932 if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) {
933 SetFlag(kIsArguments);
934 }
935 }
936
937
938 bool HPhi::HasReceiverOperand() {
939 for (int i = 0; i < OperandCount(); i++) {
940 if (OperandAt(i)->IsParameter() &&
941 HParameter::cast(OperandAt(i))->index() == 0) {
942 return true;
943 }
944 }
945 return false;
946 }
947
948
949 HValue* HPhi::GetRedundantReplacement() const {
950 HValue* candidate = NULL;
951 int count = OperandCount();
952 int position = 0;
953 while (position < count && candidate == NULL) {
954 HValue* current = OperandAt(position++);
955 if (current != this) candidate = current;
956 }
957 while (position < count) {
958 HValue* current = OperandAt(position++);
959 if (current != this && current != candidate) return NULL;
960 }
961 ASSERT(candidate != this);
962 return candidate;
963 }
964
965
966 void HPhi::DeleteFromGraph() {
967 ASSERT(block() != NULL);
968 block()->RemovePhi(this);
969 ASSERT(block() == NULL);
970 }
971
972
973 void HPhi::InitRealUses(int phi_id) {
974 // Initialize real uses.
975 phi_id_ = phi_id;
976 for (int j = 0; j < uses()->length(); j++) {
977 HValue* use = uses()->at(j);
978 if (!use->IsPhi()) {
979 int index = use->LookupOperandIndex(0, this);
980 Representation req_rep = use->RequiredInputRepresentation(index);
981 non_phi_uses_[req_rep.kind()]++;
982 }
983 }
984 }
985
986
987 void HPhi::AddNonPhiUsesFrom(HPhi* other) {
988 for (int i = 0; i < Representation::kNumRepresentations; i++) {
989 indirect_uses_[i] += other->non_phi_uses_[i];
990 }
991 }
992
993
994 void HPhi::AddIndirectUsesTo(int* dest) {
995 for (int i = 0; i < Representation::kNumRepresentations; i++) {
996 dest[i] += indirect_uses_[i];
997 }
998 }
999
1000
1001 void HSimulate::PrintDataTo(StringStream* stream) const {
1002 stream->Add("id=%d ", ast_id());
1003 if (pop_count_ > 0) stream->Add("pop %d", pop_count_);
1004 if (values_.length() > 0) {
1005 if (pop_count_ > 0) stream->Add(" /");
1006 for (int i = 0; i < values_.length(); ++i) {
1007 if (!HasAssignedIndexAt(i)) {
1008 stream->Add(" push ");
1009 } else {
1010 stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
1011 }
1012 values_[i]->PrintNameTo(stream);
1013 }
1014 }
1015 }
1016
1017
1018 void HEnterInlined::PrintDataTo(StringStream* stream) const {
1019 SmartPointer<char> name = function()->debug_name()->ToCString();
1020 stream->Add("%s, id=%d", *name, function()->id());
1021 }
1022
1023
1024 HConstant::HConstant(Handle<Object> handle, Representation r)
1025 : handle_(handle),
1026 constant_type_(HType::TypeFromValue(handle)),
1027 has_int32_value_(false),
1028 int32_value_(0),
1029 has_double_value_(false),
1030 double_value_(0) {
1031 set_representation(r);
1032 SetFlag(kUseGVN);
1033 if (handle_->IsNumber()) {
1034 double n = handle_->Number();
1035 has_int32_value_ = static_cast<double>(static_cast<int32_t>(n)) == n;
1036 if (has_int32_value_) int32_value_ = static_cast<int32_t>(n);
1037 double_value_ = n;
1038 has_double_value_ = true;
1039 }
1040 }
1041
1042
1043 HConstant* HConstant::CopyToRepresentation(Representation r) const {
1044 if (r.IsInteger32() && !has_int32_value_) return NULL;
1045 if (r.IsDouble() && !has_double_value_) return NULL;
1046 return new HConstant(handle_, r);
1047 }
1048
1049
1050 HConstant* HConstant::CopyToTruncatedInt32() const {
1051 if (!has_double_value_) return NULL;
1052 int32_t truncated = NumberToInt32(*handle_);
1053 return new HConstant(FACTORY->NewNumberFromInt(truncated),
1054 Representation::Integer32());
1055 }
1056
1057
1058 void HConstant::PrintDataTo(StringStream* stream) const {
1059 handle()->ShortPrint(stream);
1060 }
1061
1062
1063 bool HArrayLiteral::IsCopyOnWrite() const {
1064 return constant_elements()->map() == HEAP->fixed_cow_array_map();
1065 }
1066
1067
1068 void HBinaryOperation::PrintDataTo(StringStream* stream) const {
1069 left()->PrintNameTo(stream);
1070 stream->Add(" ");
1071 right()->PrintNameTo(stream);
1072 if (CheckFlag(kCanOverflow)) stream->Add(" !");
1073 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1074 }
1075
1076
1077 Range* HBitAnd::InferRange() {
1078 Range* a = left()->range();
1079 Range* b = right()->range();
1080 int32_t a_mask = 0xffffffff;
1081 int32_t b_mask = 0xffffffff;
1082 if (a != NULL) a_mask = a->Mask();
1083 if (b != NULL) b_mask = b->Mask();
1084 int32_t result_mask = a_mask & b_mask;
1085 if (result_mask >= 0) {
1086 return new Range(0, result_mask);
1087 } else {
1088 return HBinaryOperation::InferRange();
1089 }
1090 }
1091
1092
1093 Range* HBitOr::InferRange() {
1094 Range* a = left()->range();
1095 Range* b = right()->range();
1096 int32_t a_mask = 0xffffffff;
1097 int32_t b_mask = 0xffffffff;
1098 if (a != NULL) a_mask = a->Mask();
1099 if (b != NULL) b_mask = b->Mask();
1100 int32_t result_mask = a_mask | b_mask;
1101 if (result_mask >= 0) {
1102 return new Range(0, result_mask);
1103 } else {
1104 return HBinaryOperation::InferRange();
1105 }
1106 }
1107
1108
1109 Range* HSar::InferRange() {
1110 if (right()->IsConstant()) {
1111 HConstant* c = HConstant::cast(right());
1112 if (c->HasInteger32Value()) {
1113 int32_t val = c->Integer32Value();
1114 Range* result = NULL;
1115 Range* left_range = left()->range();
1116 if (left_range == NULL) {
1117 result = new Range();
1118 } else {
1119 result = left_range->Copy();
1120 }
1121 result->Sar(val);
1122 return result;
1123 }
1124 }
1125
1126 return HBinaryOperation::InferRange();
1127 }
1128
1129
1130 Range* HShl::InferRange() {
1131 if (right()->IsConstant()) {
1132 HConstant* c = HConstant::cast(right());
1133 if (c->HasInteger32Value()) {
1134 int32_t val = c->Integer32Value();
1135 Range* result = NULL;
1136 Range* left_range = left()->range();
1137 if (left_range == NULL) {
1138 result = new Range();
1139 } else {
1140 result = left_range->Copy();
1141 }
1142 result->Shl(val);
1143 return result;
1144 }
1145 }
1146
1147 return HBinaryOperation::InferRange();
1148 }
1149
1150
1151
1152 void HCompare::PrintDataTo(StringStream* stream) const {
1153 stream->Add(Token::Name(token()));
1154 stream->Add(" ");
1155 HBinaryOperation::PrintDataTo(stream);
1156 }
1157
1158
1159 void HCompare::SetInputRepresentation(Representation r) {
1160 input_representation_ = r;
1161 if (r.IsTagged()) {
1162 SetFlagMask(AllSideEffects());
1163 ClearFlag(kUseGVN);
1164 } else {
1165 ClearFlagMask(AllSideEffects());
1166 SetFlag(kUseGVN);
1167 }
1168 }
1169
1170
1171 void HParameter::PrintDataTo(StringStream* stream) const {
1172 stream->Add("%u", index());
1173 }
1174
1175
1176 void HLoadNamedField::PrintDataTo(StringStream* stream) const {
1177 object()->PrintNameTo(stream);
1178 stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1179 }
1180
1181
1182 void HLoadKeyed::PrintDataTo(StringStream* stream) const {
1183 object()->PrintNameTo(stream);
1184 stream->Add("[");
1185 key()->PrintNameTo(stream);
1186 stream->Add("]");
1187 }
1188
1189
1190 void HStoreNamed::PrintDataTo(StringStream* stream) const {
1191 object()->PrintNameTo(stream);
1192 stream->Add(".");
1193 ASSERT(name()->IsString());
1194 stream->Add(*String::cast(*name())->ToCString());
1195 stream->Add(" = ");
1196 value()->PrintNameTo(stream);
1197 }
1198
1199
1200 void HStoreNamedField::PrintDataTo(StringStream* stream) const {
1201 HStoreNamed::PrintDataTo(stream);
1202 if (!transition().is_null()) {
1203 stream->Add(" (transition map %p)", *transition());
1204 }
1205 }
1206
1207
1208 void HStoreKeyed::PrintDataTo(StringStream* stream) const {
1209 object()->PrintNameTo(stream);
1210 stream->Add("[");
1211 key()->PrintNameTo(stream);
1212 stream->Add("] = ");
1213 value()->PrintNameTo(stream);
1214 }
1215
1216
1217 void HLoadGlobal::PrintDataTo(StringStream* stream) const {
1218 stream->Add("[%p]", *cell());
1219 if (check_hole_value()) stream->Add(" (deleteable/read-only)");
1220 }
1221
1222
1223 void HStoreGlobal::PrintDataTo(StringStream* stream) const {
1224 stream->Add("[%p] = ", *cell());
1225 value()->PrintNameTo(stream);
1226 }
1227
1228
1229 // Implementation of type inference and type conversions. Calculates
1230 // the inferred type of this instruction based on the input operands.
1231
1232 HType HValue::CalculateInferredType() const {
1233 return type_;
1234 }
1235
1236
1237 HType HCheckMap::CalculateInferredType() const {
1238 return value()->type();
1239 }
1240
1241
1242 HType HCheckFunction::CalculateInferredType() const {
1243 return value()->type();
1244 }
1245
1246
1247 HType HCheckNonSmi::CalculateInferredType() const {
1248 // TODO(kasperl): Is there any way to signal that this isn't a smi?
1249 return HType::Tagged();
1250 }
1251
1252
1253 HType HCheckSmi::CalculateInferredType() const {
1254 return HType::Smi();
1255 }
1256
1257
1258 HType HPhi::CalculateInferredType() const {
1259 HType result = HType::Uninitialized();
1260 for (int i = 0; i < OperandCount(); ++i) {
1261 HType current = OperandAt(i)->type();
1262 result = result.Combine(current);
1263 }
1264 return result;
1265 }
1266
1267
1268 HType HConstant::CalculateInferredType() const {
1269 return constant_type_;
1270 }
1271
1272
1273 HType HCompare::CalculateInferredType() const {
1274 return HType::Boolean();
1275 }
1276
1277
1278 HType HCompareJSObjectEq::CalculateInferredType() const {
1279 return HType::Boolean();
1280 }
1281
1282
1283 HType HUnaryPredicate::CalculateInferredType() const {
1284 return HType::Boolean();
1285 }
1286
1287
1288 HType HArithmeticBinaryOperation::CalculateInferredType() const {
1289 return HType::TaggedNumber();
1290 }
1291
1292
1293 HType HAdd::CalculateInferredType() const {
1294 return HType::Tagged();
1295 }
1296
1297
1298 HType HBitAnd::CalculateInferredType() const {
1299 return HType::TaggedNumber();
1300 }
1301
1302
1303 HType HBitXor::CalculateInferredType() const {
1304 return HType::TaggedNumber();
1305 }
1306
1307
1308 HType HBitOr::CalculateInferredType() const {
1309 return HType::TaggedNumber();
1310 }
1311
1312
1313 HType HBitNot::CalculateInferredType() const {
1314 return HType::TaggedNumber();
1315 }
1316
1317
1318 HType HUnaryMathOperation::CalculateInferredType() const {
1319 return HType::TaggedNumber();
1320 }
1321
1322
1323 HType HShl::CalculateInferredType() const {
1324 return HType::TaggedNumber();
1325 }
1326
1327
1328 HType HShr::CalculateInferredType() const {
1329 return HType::TaggedNumber();
1330 }
1331
1332
1333 HType HSar::CalculateInferredType() const {
1334 return HType::TaggedNumber();
1335 }
1336
1337
1338 HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero(
1339 BitVector* visited) {
1340 visited->Add(id());
1341 if (representation().IsInteger32() &&
1342 !value()->representation().IsInteger32()) {
1343 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
1344 SetFlag(kBailoutOnMinusZero);
1345 }
1346 }
1347 if (RequiredInputRepresentation(0).IsInteger32() &&
1348 representation().IsInteger32()) {
1349 return value();
1350 }
1351 return NULL;
1352 }
1353
1354
1355
1356 HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1357 visited->Add(id());
1358 if (from().IsInteger32()) return NULL;
1359 if (CanTruncateToInt32()) return NULL;
1360 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
1361 SetFlag(kBailoutOnMinusZero);
1362 }
1363 ASSERT(!from().IsInteger32() || !to().IsInteger32());
1364 return NULL;
1365 }
1366
1367
1368 HValue* HMod::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1369 visited->Add(id());
1370 if (range() == NULL || range()->CanBeMinusZero()) {
1371 SetFlag(kBailoutOnMinusZero);
1372 return left();
1373 }
1374 return NULL;
1375 }
1376
1377
1378 HValue* HDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1379 visited->Add(id());
1380 if (range() == NULL || range()->CanBeMinusZero()) {
1381 SetFlag(kBailoutOnMinusZero);
1382 }
1383 return NULL;
1384 }
1385
1386
1387 HValue* HMul::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1388 visited->Add(id());
1389 if (range() == NULL || range()->CanBeMinusZero()) {
1390 SetFlag(kBailoutOnMinusZero);
1391 }
1392 return NULL;
1393 }
1394
1395
1396 HValue* HSub::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1397 visited->Add(id());
1398 // Propagate to the left argument. If the left argument cannot be -0, then
1399 // the result of the add operation cannot be either.
1400 if (range() == NULL || range()->CanBeMinusZero()) {
1401 return left();
1402 }
1403 return NULL;
1404 }
1405
1406
1407 HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1408 visited->Add(id());
1409 // Propagate to the left argument. If the left argument cannot be -0, then
1410 // the result of the sub operation cannot be either.
1411 if (range() == NULL || range()->CanBeMinusZero()) {
1412 return left();
1413 }
1414 return NULL;
1415 }
1416
1417
1418 // Node-specific verification code is only included in debug mode.
1419 #ifdef DEBUG
1420
1421 void HPhi::Verify() const {
1422 ASSERT(OperandCount() == block()->predecessors()->length());
1423 for (int i = 0; i < OperandCount(); ++i) {
1424 HValue* value = OperandAt(i);
1425 HBasicBlock* defining_block = value->block();
1426 HBasicBlock* predecessor_block = block()->predecessors()->at(i);
1427 ASSERT(defining_block == predecessor_block ||
1428 defining_block->Dominates(predecessor_block));
1429 }
1430 }
1431
1432
1433 void HSimulate::Verify() const {
1434 HInstruction::Verify();
1435 ASSERT(HasAstId());
1436 }
1437
1438
1439 void HBoundsCheck::Verify() const {
1440 HInstruction::Verify();
1441 ASSERT(HasNoUses());
1442 }
1443
1444
1445 void HCheckSmi::Verify() const {
1446 HInstruction::Verify();
1447 ASSERT(HasNoUses());
1448 }
1449
1450
1451 void HCheckNonSmi::Verify() const {
1452 HInstruction::Verify();
1453 ASSERT(HasNoUses());
1454 }
1455
1456
1457 void HCheckInstanceType::Verify() const {
1458 HInstruction::Verify();
1459 ASSERT(HasNoUses());
1460 }
1461
1462
1463 void HCheckMap::Verify() const {
1464 HInstruction::Verify();
1465 ASSERT(HasNoUses());
1466 }
1467
1468
1469 void HCheckFunction::Verify() const {
1470 HInstruction::Verify();
1471 ASSERT(HasNoUses());
1472 }
1473
1474
1475 void HCheckPrototypeMaps::Verify() const {
1476 HInstruction::Verify();
1477 ASSERT(HasNoUses());
1478 }
1479
1480 #endif
1481
1482 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698