blob: 18e3b4532d5630668958e7e63dca6b568aae5531 [file] [log] [blame]
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001// Copyright 2011 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002// 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"
lrn@chromium.org7516f052011-03-30 08:52:27 +000039#elif V8_TARGET_ARCH_MIPS
40#include "mips/lithium-mips.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000041#else
42#error Unsupported target architecture.
43#endif
44
45namespace v8 {
46namespace internal {
47
48#define DEFINE_COMPILE(type) \
49 LInstruction* H##type::CompileToLithium(LChunkBuilder* builder) { \
50 return builder->Do##type(this); \
51 }
52HYDROGEN_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
53#undef DEFINE_COMPILE
54
55
56const char* Representation::Mnemonic() const {
57 switch (kind_) {
58 case kNone: return "v";
59 case kTagged: return "t";
60 case kDouble: return "d";
61 case kInteger32: return "i";
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000062 case kExternal: return "x";
karlklose@chromium.org83a47282011-05-11 11:54:09 +000063 default:
kasperl@chromium.orga5551262010-12-07 12:49:48 +000064 UNREACHABLE();
65 return NULL;
66 }
67}
68
69
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000070void HValue::AssumeRepresentation(Representation r) {
71 if (CheckFlag(kFlexibleRepresentation)) {
72 ChangeRepresentation(r);
73 // The representation of the value is dictated by type feedback and
74 // will not be changed later.
75 ClearFlag(kFlexibleRepresentation);
76 }
77}
78
79
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000080static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
81 if (result > kMaxInt) {
82 *overflow = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000083 return kMaxInt;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000084 }
85 if (result < kMinInt) {
86 *overflow = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000087 return kMinInt;
88 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000089 return static_cast<int32_t>(result);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000090}
91
92
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000093static int32_t AddWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
94 int64_t result = static_cast<int64_t>(a) + static_cast<int64_t>(b);
95 return ConvertAndSetOverflow(result, overflow);
96}
97
98
99static int32_t SubWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
100 int64_t result = static_cast<int64_t>(a) - static_cast<int64_t>(b);
101 return ConvertAndSetOverflow(result, overflow);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000102}
103
104
105static int32_t MulWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000106 int64_t result = static_cast<int64_t>(a) * static_cast<int64_t>(b);
107 return ConvertAndSetOverflow(result, overflow);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000108}
109
110
111int32_t Range::Mask() const {
112 if (lower_ == upper_) return lower_;
113 if (lower_ >= 0) {
114 int32_t res = 1;
115 while (res < upper_) {
116 res = (res << 1) | 1;
117 }
118 return res;
119 }
120 return 0xffffffff;
121}
122
123
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000124void Range::AddConstant(int32_t value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000125 if (value == 0) return;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000126 bool may_overflow = false; // Overflow is ignored here.
127 lower_ = AddWithoutOverflow(lower_, value, &may_overflow);
128 upper_ = AddWithoutOverflow(upper_, value, &may_overflow);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000129 Verify();
130}
131
132
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000133void Range::Intersect(Range* other) {
134 upper_ = Min(upper_, other->upper_);
135 lower_ = Max(lower_, other->lower_);
136 bool b = CanBeMinusZero() && other->CanBeMinusZero();
137 set_can_be_minus_zero(b);
138}
139
140
141void Range::Union(Range* other) {
142 upper_ = Max(upper_, other->upper_);
143 lower_ = Min(lower_, other->lower_);
144 bool b = CanBeMinusZero() || other->CanBeMinusZero();
145 set_can_be_minus_zero(b);
146}
147
148
149void Range::Sar(int32_t value) {
150 int32_t bits = value & 0x1F;
151 lower_ = lower_ >> bits;
152 upper_ = upper_ >> bits;
153 set_can_be_minus_zero(false);
154}
155
156
157void Range::Shl(int32_t value) {
158 int32_t bits = value & 0x1F;
159 int old_lower = lower_;
160 int old_upper = upper_;
161 lower_ = lower_ << bits;
162 upper_ = upper_ << bits;
163 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
164 upper_ = kMaxInt;
165 lower_ = kMinInt;
166 }
167 set_can_be_minus_zero(false);
168}
169
170
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000171bool Range::AddAndCheckOverflow(Range* other) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000172 bool may_overflow = false;
173 lower_ = AddWithoutOverflow(lower_, other->lower(), &may_overflow);
174 upper_ = AddWithoutOverflow(upper_, other->upper(), &may_overflow);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000175 KeepOrder();
176 Verify();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000177 return may_overflow;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000178}
179
180
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000181bool Range::SubAndCheckOverflow(Range* other) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000182 bool may_overflow = false;
183 lower_ = SubWithoutOverflow(lower_, other->upper(), &may_overflow);
184 upper_ = SubWithoutOverflow(upper_, other->lower(), &may_overflow);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000185 KeepOrder();
186 Verify();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000187 return may_overflow;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000188}
189
190
191void Range::KeepOrder() {
192 if (lower_ > upper_) {
193 int32_t tmp = lower_;
194 lower_ = upper_;
195 upper_ = tmp;
196 }
197}
198
199
200void Range::Verify() const {
201 ASSERT(lower_ <= upper_);
202}
203
204
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000205bool Range::MulAndCheckOverflow(Range* other) {
206 bool may_overflow = false;
207 int v1 = MulWithoutOverflow(lower_, other->lower(), &may_overflow);
208 int v2 = MulWithoutOverflow(lower_, other->upper(), &may_overflow);
209 int v3 = MulWithoutOverflow(upper_, other->lower(), &may_overflow);
210 int v4 = MulWithoutOverflow(upper_, other->upper(), &may_overflow);
211 lower_ = Min(Min(v1, v2), Min(v3, v4));
212 upper_ = Max(Max(v1, v2), Max(v3, v4));
213 Verify();
214 return may_overflow;
215}
216
217
218const char* HType::ToString() {
219 switch (type_) {
220 case kTagged: return "tagged";
221 case kTaggedPrimitive: return "primitive";
222 case kTaggedNumber: return "number";
223 case kSmi: return "smi";
224 case kHeapNumber: return "heap-number";
225 case kString: return "string";
226 case kBoolean: return "boolean";
227 case kNonPrimitive: return "non-primitive";
228 case kJSArray: return "array";
229 case kJSObject: return "object";
230 case kUninitialized: return "uninitialized";
231 }
232 UNREACHABLE();
233 return "Unreachable code";
234}
235
236
237const char* HType::ToShortString() {
238 switch (type_) {
239 case kTagged: return "t";
240 case kTaggedPrimitive: return "p";
241 case kTaggedNumber: return "n";
242 case kSmi: return "m";
243 case kHeapNumber: return "h";
244 case kString: return "s";
245 case kBoolean: return "b";
246 case kNonPrimitive: return "r";
247 case kJSArray: return "a";
248 case kJSObject: return "o";
249 case kUninitialized: return "z";
250 }
251 UNREACHABLE();
252 return "Unreachable code";
253}
254
255
256HType HType::TypeFromValue(Handle<Object> value) {
257 HType result = HType::Tagged();
258 if (value->IsSmi()) {
259 result = HType::Smi();
260 } else if (value->IsHeapNumber()) {
261 result = HType::HeapNumber();
262 } else if (value->IsString()) {
263 result = HType::String();
264 } else if (value->IsBoolean()) {
265 result = HType::Boolean();
266 } else if (value->IsJSObject()) {
267 result = HType::JSObject();
268 } else if (value->IsJSArray()) {
269 result = HType::JSArray();
270 }
271 return result;
272}
273
274
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000275bool HValue::IsDefinedAfter(HBasicBlock* other) const {
276 return block()->block_id() > other->block_id();
277}
278
279
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000280HUseIterator::HUseIterator(HUseListNode* head) : next_(head) {
281 Advance();
282}
283
284
285void HUseIterator::Advance() {
286 current_ = next_;
287 if (current_ != NULL) {
288 next_ = current_->tail();
289 value_ = current_->value();
290 index_ = current_->index();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000291 }
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000292}
293
294
295int HValue::UseCount() const {
296 int count = 0;
297 for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count;
298 return count;
299}
300
301
302HUseListNode* HValue::RemoveUse(HValue* value, int index) {
303 HUseListNode* previous = NULL;
304 HUseListNode* current = use_list_;
305 while (current != NULL) {
306 if (current->value() == value && current->index() == index) {
307 if (previous == NULL) {
308 use_list_ = current->tail();
309 } else {
310 previous->set_tail(current->tail());
311 }
312 break;
313 }
314
315 previous = current;
316 current = current->tail();
317 }
318
319#ifdef DEBUG
320 // Do not reuse use list nodes in debug mode, zap them.
321 if (current != NULL) {
322 HUseListNode* temp =
323 new HUseListNode(current->value(), current->index(), NULL);
324 current->Zap();
325 current = temp;
326 }
327#endif
328 return current;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000329}
330
331
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000332bool HValue::Equals(HValue* other) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000333 if (other->opcode() != opcode()) return false;
334 if (!other->representation().Equals(representation())) return false;
335 if (!other->type_.Equals(type_)) return false;
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000336 if (other->flags() != flags()) return false;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000337 if (OperandCount() != other->OperandCount()) return false;
338 for (int i = 0; i < OperandCount(); ++i) {
339 if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false;
340 }
341 bool result = DataEquals(other);
342 ASSERT(!result || Hashcode() == other->Hashcode());
343 return result;
344}
345
346
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000347intptr_t HValue::Hashcode() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000348 intptr_t result = opcode();
349 int count = OperandCount();
350 for (int i = 0; i < count; ++i) {
351 result = result * 19 + OperandAt(i)->id() + (result >> 7);
352 }
353 return result;
354}
355
356
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000357const char* HValue::Mnemonic() const {
358 switch (opcode()) {
359#define MAKE_CASE(type) case k##type: return #type;
360 HYDROGEN_CONCRETE_INSTRUCTION_LIST(MAKE_CASE)
361#undef MAKE_CASE
362 case kPhi: return "Phi";
363 default: return "";
364 }
365}
366
367
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000368void HValue::SetOperandAt(int index, HValue* value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000369 RegisterUse(index, value);
370 InternalSetOperandAt(index, value);
371}
372
373
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000374void HValue::DeleteAndReplaceWith(HValue* other) {
375 // We replace all uses first, so Delete can assert that there are none.
376 if (other != NULL) ReplaceAllUsesWith(other);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000377 ASSERT(HasNoUses());
378 ClearOperands();
379 DeleteFromGraph();
380}
381
382
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000383void HValue::ReplaceAllUsesWith(HValue* other) {
384 while (use_list_ != NULL) {
385 HUseListNode* list_node = use_list_;
386 HValue* value = list_node->value();
387 ASSERT(!value->block()->IsStartBlock());
388 value->InternalSetOperandAt(list_node->index(), other);
389 use_list_ = list_node->tail();
390 list_node->set_tail(other->use_list_);
391 other->use_list_ = list_node;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000392 }
393}
394
395
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000396void HValue::ClearOperands() {
397 for (int i = 0; i < OperandCount(); ++i) {
398 SetOperandAt(i, NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000399 }
400}
401
402
403void HValue::SetBlock(HBasicBlock* block) {
404 ASSERT(block_ == NULL || block == NULL);
405 block_ = block;
406 if (id_ == kNoNumber && block != NULL) {
407 id_ = block->graph()->GetNextValueID(this);
408 }
409}
410
411
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000412void HValue::PrintTypeTo(StringStream* stream) {
413 if (!representation().IsTagged() || type().Equals(HType::Tagged())) return;
414 stream->Add(" type[%s]", type().ToString());
415}
416
417
418void HValue::PrintRangeTo(StringStream* stream) {
419 if (range() == NULL || range()->IsMostGeneric()) return;
420 stream->Add(" range[%d,%d,m0=%d]",
421 range()->lower(),
422 range()->upper(),
423 static_cast<int>(range()->CanBeMinusZero()));
424}
425
426
427void HValue::PrintChangesTo(StringStream* stream) {
428 int changes_flags = (flags() & HValue::ChangesFlagsMask());
429 if (changes_flags == 0) return;
430 stream->Add(" changes[");
431 if (changes_flags == AllSideEffects()) {
432 stream->Add("*");
433 } else {
434 bool add_comma = false;
435#define PRINT_DO(type) \
436 if (changes_flags & (1 << kChanges##type)) { \
437 if (add_comma) stream->Add(","); \
438 add_comma = true; \
439 stream->Add(#type); \
440 }
441 GVN_FLAG_LIST(PRINT_DO);
442#undef PRINT_DO
443 }
444 stream->Add("]");
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000445}
446
447
448void HValue::PrintNameTo(StringStream* stream) {
449 stream->Add("%s%d", representation_.Mnemonic(), id());
450}
451
452
453bool HValue::UpdateInferredType() {
454 HType type = CalculateInferredType();
455 bool result = (!type.Equals(type_));
456 type_ = type;
457 return result;
458}
459
460
461void HValue::RegisterUse(int index, HValue* new_value) {
462 HValue* old_value = OperandAt(index);
463 if (old_value == new_value) return;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000464
465 HUseListNode* removed = NULL;
466 if (old_value != NULL) {
467 removed = old_value->RemoveUse(this, index);
468 }
469
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000470 if (new_value != NULL) {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000471 if (removed == NULL) {
472 new_value->use_list_ =
473 new HUseListNode(this, index, new_value->use_list_);
474 } else {
475 removed->set_tail(new_value->use_list_);
476 new_value->use_list_ = removed;
477 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000478 }
479}
480
481
482void HValue::AddNewRange(Range* r) {
483 if (!HasRange()) ComputeInitialRange();
484 if (!HasRange()) range_ = new Range();
485 ASSERT(HasRange());
486 r->StackUpon(range_);
487 range_ = r;
488}
489
490
491void HValue::RemoveLastAddedRange() {
492 ASSERT(HasRange());
493 ASSERT(range_->next() != NULL);
494 range_ = range_->next();
495}
496
497
498void HValue::ComputeInitialRange() {
499 ASSERT(!HasRange());
500 range_ = InferRange();
501 ASSERT(HasRange());
502}
503
504
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000505void HInstruction::PrintTo(StringStream* stream) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000506 PrintMnemonicTo(stream);
507 PrintDataTo(stream);
508 PrintRangeTo(stream);
509 PrintChangesTo(stream);
510 PrintTypeTo(stream);
511}
512
513
514void HInstruction::PrintMnemonicTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000515 stream->Add("%s", Mnemonic());
516 if (HasSideEffects()) stream->Add("*");
517 stream->Add(" ");
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000518}
519
520
521void HInstruction::Unlink() {
522 ASSERT(IsLinked());
523 ASSERT(!IsControlInstruction()); // Must never move control instructions.
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000524 ASSERT(!IsBlockEntry()); // Doesn't make sense to delete these.
525 ASSERT(previous_ != NULL);
526 previous_->next_ = next_;
527 if (next_ == NULL) {
528 ASSERT(block()->last() == this);
529 block()->set_last(previous_);
530 } else {
531 next_->previous_ = previous_;
532 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000533 clear_block();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000534}
535
536
537void HInstruction::InsertBefore(HInstruction* next) {
538 ASSERT(!IsLinked());
539 ASSERT(!next->IsBlockEntry());
540 ASSERT(!IsControlInstruction());
541 ASSERT(!next->block()->IsStartBlock());
542 ASSERT(next->previous_ != NULL);
543 HInstruction* prev = next->previous();
544 prev->next_ = this;
545 next->previous_ = this;
546 next_ = next;
547 previous_ = prev;
548 SetBlock(next->block());
549}
550
551
552void HInstruction::InsertAfter(HInstruction* previous) {
553 ASSERT(!IsLinked());
554 ASSERT(!previous->IsControlInstruction());
555 ASSERT(!IsControlInstruction() || previous->next_ == NULL);
556 HBasicBlock* block = previous->block();
557 // Never insert anything except constants into the start block after finishing
558 // it.
559 if (block->IsStartBlock() && block->IsFinished() && !IsConstant()) {
560 ASSERT(block->end()->SecondSuccessor() == NULL);
561 InsertAfter(block->end()->FirstSuccessor()->first());
562 return;
563 }
564
565 // If we're inserting after an instruction with side-effects that is
566 // followed by a simulate instruction, we need to insert after the
567 // simulate instruction instead.
568 HInstruction* next = previous->next_;
569 if (previous->HasSideEffects() && next != NULL) {
570 ASSERT(next->IsSimulate());
571 previous = next;
572 next = previous->next_;
573 }
574
575 previous_ = previous;
576 next_ = next;
577 SetBlock(block);
578 previous->next_ = this;
579 if (next != NULL) next->previous_ = this;
580}
581
582
583#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000584void HInstruction::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000585 // Verify that input operands are defined before use.
586 HBasicBlock* cur_block = block();
587 for (int i = 0; i < OperandCount(); ++i) {
588 HValue* other_operand = OperandAt(i);
589 HBasicBlock* other_block = other_operand->block();
590 if (cur_block == other_block) {
591 if (!other_operand->IsPhi()) {
592 HInstruction* cur = cur_block->first();
593 while (cur != NULL) {
594 ASSERT(cur != this); // We should reach other_operand before!
595 if (cur == other_operand) break;
596 cur = cur->next();
597 }
598 // Must reach other operand in the same block!
599 ASSERT(cur == other_operand);
600 }
601 } else {
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000602 // If the following assert fires, you may have forgotten an
603 // AddInstruction.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000604 ASSERT(other_block->Dominates(cur_block));
605 }
606 }
607
608 // Verify that instructions that may have side-effects are followed
609 // by a simulate instruction.
610 if (HasSideEffects() && !IsOsrEntry()) {
611 ASSERT(next()->IsSimulate());
612 }
ager@chromium.org378b34e2011-01-28 08:04:38 +0000613
614 // Verify that instructions that can be eliminated by GVN have overridden
615 // HValue::DataEquals. The default implementation is UNREACHABLE. We
616 // don't actually care whether DataEquals returns true or false here.
617 if (CheckFlag(kUseGVN)) DataEquals(this);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000618}
619#endif
620
621
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000622void HUnaryCall::PrintDataTo(StringStream* stream) {
623 value()->PrintNameTo(stream);
624 stream->Add(" ");
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000625 stream->Add("#%d", argument_count());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000626}
627
628
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000629void HBinaryCall::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000630 first()->PrintNameTo(stream);
631 stream->Add(" ");
632 second()->PrintNameTo(stream);
633 stream->Add(" ");
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000634 stream->Add("#%d", argument_count());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000635}
636
637
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000638void HCallConstantFunction::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000639 if (IsApplyFunction()) {
640 stream->Add("optimized apply ");
641 } else {
642 stream->Add("%o ", function()->shared()->DebugName());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000643 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000644 stream->Add("#%d", argument_count());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000645}
646
647
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000648void HCallNamed::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000649 stream->Add("%o ", *name());
650 HUnaryCall::PrintDataTo(stream);
651}
652
653
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000654void HCallGlobal::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000655 stream->Add("%o ", *name());
656 HUnaryCall::PrintDataTo(stream);
657}
658
659
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000660void HCallKnownGlobal::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000661 stream->Add("o ", target()->shared()->DebugName());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000662 stream->Add("#%d", argument_count());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000663}
664
665
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000666void HCallRuntime::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000667 stream->Add("%o ", *name());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000668 stream->Add("#%d", argument_count());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000669}
670
671
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000672void HClassOfTest::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000673 stream->Add("class_of_test(");
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000674 value()->PrintNameTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000675 stream->Add(", \"%o\")", *class_name());
676}
677
678
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000679void HAccessArgumentsAt::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000680 arguments()->PrintNameTo(stream);
681 stream->Add("[");
682 index()->PrintNameTo(stream);
683 stream->Add("], length ");
684 length()->PrintNameTo(stream);
685}
686
687
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000688void HControlInstruction::PrintDataTo(StringStream* stream) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000689 stream->Add(" goto (");
690 bool first_block = true;
691 for (HSuccessorIterator it(this); !it.Done(); it.Advance()) {
692 stream->Add(first_block ? "B%d" : ", B%d", it.Current()->block_id());
693 first_block = false;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000694 }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000695 stream->Add(")");
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000696}
697
698
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000699void HUnaryControlInstruction::PrintDataTo(StringStream* stream) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000700 value()->PrintNameTo(stream);
701 HControlInstruction::PrintDataTo(stream);
702}
703
704
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000705void HReturn::PrintDataTo(StringStream* stream) {
706 value()->PrintNameTo(stream);
707}
708
709
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000710void HCompareMap::PrintDataTo(StringStream* stream) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000711 value()->PrintNameTo(stream);
712 stream->Add(" (%p)", *map());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000713 HControlInstruction::PrintDataTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000714}
715
716
717const char* HUnaryMathOperation::OpName() const {
718 switch (op()) {
719 case kMathFloor: return "floor";
720 case kMathRound: return "round";
721 case kMathCeil: return "ceil";
722 case kMathAbs: return "abs";
723 case kMathLog: return "log";
724 case kMathSin: return "sin";
725 case kMathCos: return "cos";
726 case kMathTan: return "tan";
727 case kMathASin: return "asin";
728 case kMathACos: return "acos";
729 case kMathATan: return "atan";
730 case kMathExp: return "exp";
731 case kMathSqrt: return "sqrt";
732 default: break;
733 }
734 return "(unknown operation)";
735}
736
737
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000738void HUnaryMathOperation::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000739 const char* name = OpName();
740 stream->Add("%s ", name);
741 value()->PrintNameTo(stream);
742}
743
744
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000745void HUnaryOperation::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000746 value()->PrintNameTo(stream);
747}
748
749
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000750void HHasInstanceType::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000751 value()->PrintNameTo(stream);
752 switch (from_) {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000753 case FIRST_JS_RECEIVER_TYPE:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000754 if (to_ == LAST_TYPE) stream->Add(" spec_object");
755 break;
756 case JS_REGEXP_TYPE:
757 if (to_ == JS_REGEXP_TYPE) stream->Add(" reg_exp");
758 break;
759 case JS_ARRAY_TYPE:
760 if (to_ == JS_ARRAY_TYPE) stream->Add(" array");
761 break;
762 case JS_FUNCTION_TYPE:
763 if (to_ == JS_FUNCTION_TYPE) stream->Add(" function");
764 break;
765 default:
766 break;
767 }
768}
769
770
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000771void HTypeofIs::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000772 value()->PrintNameTo(stream);
773 stream->Add(" == ");
774 stream->Add(type_literal_->ToAsciiVector());
775}
776
777
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000778void HChange::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000779 HUnaryOperation::PrintDataTo(stream);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000780 stream->Add(" %s to %s", from_.Mnemonic(), to().Mnemonic());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000781
782 if (CanTruncateToInt32()) stream->Add(" truncating-int32");
783 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
784}
785
786
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000787void HCheckInstanceType::GetCheckInterval(InstanceType* first,
788 InstanceType* last) {
789 ASSERT(is_interval_check());
790 switch (check_) {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000791 case IS_SPEC_OBJECT:
792 *first = FIRST_SPEC_OBJECT_TYPE;
793 *last = LAST_SPEC_OBJECT_TYPE;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000794 return;
795 case IS_JS_ARRAY:
796 *first = *last = JS_ARRAY_TYPE;
797 return;
798 default:
799 UNREACHABLE();
800 }
801}
802
803
804void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
805 ASSERT(!is_interval_check());
806 switch (check_) {
807 case IS_STRING:
808 *mask = kIsNotStringMask;
809 *tag = kStringTag;
810 return;
811 case IS_SYMBOL:
812 *mask = kIsSymbolMask;
813 *tag = kSymbolTag;
814 return;
815 default:
816 UNREACHABLE();
817 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000818}
819
820
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000821void HCheckMap::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000822 value()->PrintNameTo(stream);
823 stream->Add(" %p", *map());
824}
825
826
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000827void HCheckFunction::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000828 value()->PrintNameTo(stream);
829 stream->Add(" %p", *target());
830}
831
832
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000833void HCallStub::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000834 stream->Add("%s ",
835 CodeStub::MajorName(major_key_, false));
836 HUnaryCall::PrintDataTo(stream);
837}
838
839
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000840void HInstanceOf::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000841 left()->PrintNameTo(stream);
842 stream->Add(" ");
843 right()->PrintNameTo(stream);
844 stream->Add(" ");
845 context()->PrintNameTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000846}
847
848
849Range* HValue::InferRange() {
850 if (representation().IsTagged()) {
851 // Tagged values are always in int32 range when converted to integer,
852 // but they can contain -0.
853 Range* result = new Range();
854 result->set_can_be_minus_zero(true);
855 return result;
856 } else if (representation().IsNone()) {
857 return NULL;
858 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000859 // Untagged integer32 cannot be -0 and we don't compute ranges for
860 // untagged doubles.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000861 return new Range();
862 }
863}
864
865
866Range* HConstant::InferRange() {
867 if (has_int32_value_) {
868 Range* result = new Range(int32_value_, int32_value_);
869 result->set_can_be_minus_zero(false);
870 return result;
871 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000872 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000873}
874
875
876Range* HPhi::InferRange() {
877 if (representation().IsInteger32()) {
878 if (block()->IsLoopHeader()) {
879 Range* range = new Range(kMinInt, kMaxInt);
880 return range;
881 } else {
882 Range* range = OperandAt(0)->range()->Copy();
883 for (int i = 1; i < OperandCount(); ++i) {
884 range->Union(OperandAt(i)->range());
885 }
886 return range;
887 }
888 } else {
889 return HValue::InferRange();
890 }
891}
892
893
894Range* HAdd::InferRange() {
895 if (representation().IsInteger32()) {
896 Range* a = left()->range();
897 Range* b = right()->range();
898 Range* res = a->Copy();
899 if (!res->AddAndCheckOverflow(b)) {
900 ClearFlag(kCanOverflow);
901 }
902 bool m0 = a->CanBeMinusZero() && b->CanBeMinusZero();
903 res->set_can_be_minus_zero(m0);
904 return res;
905 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000906 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000907 }
908}
909
910
911Range* HSub::InferRange() {
912 if (representation().IsInteger32()) {
913 Range* a = left()->range();
914 Range* b = right()->range();
915 Range* res = a->Copy();
916 if (!res->SubAndCheckOverflow(b)) {
917 ClearFlag(kCanOverflow);
918 }
919 res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
920 return res;
921 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000922 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000923 }
924}
925
926
927Range* HMul::InferRange() {
928 if (representation().IsInteger32()) {
929 Range* a = left()->range();
930 Range* b = right()->range();
931 Range* res = a->Copy();
932 if (!res->MulAndCheckOverflow(b)) {
933 ClearFlag(kCanOverflow);
934 }
935 bool m0 = (a->CanBeZero() && b->CanBeNegative()) ||
936 (a->CanBeNegative() && b->CanBeZero());
937 res->set_can_be_minus_zero(m0);
938 return res;
939 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000940 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000941 }
942}
943
944
945Range* HDiv::InferRange() {
946 if (representation().IsInteger32()) {
947 Range* result = new Range();
948 if (left()->range()->CanBeMinusZero()) {
949 result->set_can_be_minus_zero(true);
950 }
951
952 if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) {
953 result->set_can_be_minus_zero(true);
954 }
955
956 if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
957 SetFlag(HValue::kCanOverflow);
958 }
959
960 if (!right()->range()->CanBeZero()) {
961 ClearFlag(HValue::kCanBeDivByZero);
962 }
963 return result;
964 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000965 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000966 }
967}
968
969
970Range* HMod::InferRange() {
971 if (representation().IsInteger32()) {
972 Range* a = left()->range();
973 Range* result = new Range();
974 if (a->CanBeMinusZero() || a->CanBeNegative()) {
975 result->set_can_be_minus_zero(true);
976 }
977 if (!right()->range()->CanBeZero()) {
978 ClearFlag(HValue::kCanBeDivByZero);
979 }
980 return result;
981 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000982 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000983 }
984}
985
986
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000987void HPhi::PrintTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000988 stream->Add("[");
989 for (int i = 0; i < OperandCount(); ++i) {
990 HValue* value = OperandAt(i);
991 stream->Add(" ");
992 value->PrintNameTo(stream);
993 stream->Add(" ");
994 }
995 stream->Add(" uses%d_%di_%dd_%dt]",
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000996 UseCount(),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000997 int32_non_phi_uses() + int32_indirect_uses(),
998 double_non_phi_uses() + double_indirect_uses(),
999 tagged_non_phi_uses() + tagged_indirect_uses());
1000}
1001
1002
1003void HPhi::AddInput(HValue* value) {
1004 inputs_.Add(NULL);
1005 SetOperandAt(OperandCount() - 1, value);
1006 // Mark phis that may have 'arguments' directly or indirectly as an operand.
1007 if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) {
1008 SetFlag(kIsArguments);
1009 }
1010}
1011
1012
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001013bool HPhi::HasRealUses() {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001014 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1015 if (!it.value()->IsPhi()) return true;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001016 }
1017 return false;
1018}
1019
1020
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001021HValue* HPhi::GetRedundantReplacement() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001022 HValue* candidate = NULL;
1023 int count = OperandCount();
1024 int position = 0;
1025 while (position < count && candidate == NULL) {
1026 HValue* current = OperandAt(position++);
1027 if (current != this) candidate = current;
1028 }
1029 while (position < count) {
1030 HValue* current = OperandAt(position++);
1031 if (current != this && current != candidate) return NULL;
1032 }
1033 ASSERT(candidate != this);
1034 return candidate;
1035}
1036
1037
1038void HPhi::DeleteFromGraph() {
1039 ASSERT(block() != NULL);
1040 block()->RemovePhi(this);
1041 ASSERT(block() == NULL);
1042}
1043
1044
1045void HPhi::InitRealUses(int phi_id) {
1046 // Initialize real uses.
1047 phi_id_ = phi_id;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001048 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1049 HValue* value = it.value();
1050 if (!value->IsPhi()) {
1051 Representation rep = value->RequiredInputRepresentation(it.index());
1052 ++non_phi_uses_[rep.kind()];
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001053 }
1054 }
1055}
1056
1057
1058void HPhi::AddNonPhiUsesFrom(HPhi* other) {
1059 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1060 indirect_uses_[i] += other->non_phi_uses_[i];
1061 }
1062}
1063
1064
1065void HPhi::AddIndirectUsesTo(int* dest) {
1066 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1067 dest[i] += indirect_uses_[i];
1068 }
1069}
1070
1071
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001072void HSimulate::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001073 stream->Add("id=%d ", ast_id());
1074 if (pop_count_ > 0) stream->Add("pop %d", pop_count_);
1075 if (values_.length() > 0) {
1076 if (pop_count_ > 0) stream->Add(" /");
1077 for (int i = 0; i < values_.length(); ++i) {
1078 if (!HasAssignedIndexAt(i)) {
1079 stream->Add(" push ");
1080 } else {
1081 stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
1082 }
1083 values_[i]->PrintNameTo(stream);
1084 }
1085 }
1086}
1087
1088
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00001089void HDeoptimize::PrintDataTo(StringStream* stream) {
1090 if (OperandCount() == 0) return;
1091 OperandAt(0)->PrintNameTo(stream);
1092 for (int i = 1; i < OperandCount(); ++i) {
1093 stream->Add(" ");
1094 OperandAt(i)->PrintNameTo(stream);
1095 }
1096}
1097
1098
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001099void HEnterInlined::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001100 SmartPointer<char> name = function()->debug_name()->ToCString();
1101 stream->Add("%s, id=%d", *name, function()->id());
1102}
1103
1104
1105HConstant::HConstant(Handle<Object> handle, Representation r)
1106 : handle_(handle),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001107 has_int32_value_(false),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001108 has_double_value_(false),
danno@chromium.org160a7b02011-04-18 15:51:38 +00001109 int32_value_(0),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001110 double_value_(0) {
1111 set_representation(r);
1112 SetFlag(kUseGVN);
1113 if (handle_->IsNumber()) {
1114 double n = handle_->Number();
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001115 double roundtrip_value = static_cast<double>(static_cast<int32_t>(n));
1116 has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001117 if (has_int32_value_) int32_value_ = static_cast<int32_t>(n);
1118 double_value_ = n;
1119 has_double_value_ = true;
1120 }
1121}
1122
1123
1124HConstant* HConstant::CopyToRepresentation(Representation r) const {
1125 if (r.IsInteger32() && !has_int32_value_) return NULL;
1126 if (r.IsDouble() && !has_double_value_) return NULL;
1127 return new HConstant(handle_, r);
1128}
1129
1130
1131HConstant* HConstant::CopyToTruncatedInt32() const {
1132 if (!has_double_value_) return NULL;
1133 int32_t truncated = NumberToInt32(*handle_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001134 return new HConstant(FACTORY->NewNumberFromInt(truncated),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001135 Representation::Integer32());
1136}
1137
1138
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001139bool HConstant::ToBoolean() const {
1140 // Converts the constant's boolean value according to
1141 // ECMAScript section 9.2 ToBoolean conversion.
1142 if (HasInteger32Value()) return Integer32Value() != 0;
1143 if (HasDoubleValue()) {
1144 double v = DoubleValue();
1145 return v != 0 && !isnan(v);
1146 }
1147 if (handle()->IsTrue()) return true;
1148 if (handle()->IsFalse()) return false;
1149 if (handle()->IsUndefined()) return false;
1150 if (handle()->IsNull()) return false;
1151 if (handle()->IsString() &&
1152 String::cast(*handle())->length() == 0) return false;
1153 return true;
1154}
1155
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001156void HConstant::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001157 handle()->ShortPrint(stream);
1158}
1159
1160
1161bool HArrayLiteral::IsCopyOnWrite() const {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001162 return constant_elements()->map() == HEAP->fixed_cow_array_map();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001163}
1164
1165
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001166void HBinaryOperation::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001167 left()->PrintNameTo(stream);
1168 stream->Add(" ");
1169 right()->PrintNameTo(stream);
1170 if (CheckFlag(kCanOverflow)) stream->Add(" !");
1171 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1172}
1173
1174
1175Range* HBitAnd::InferRange() {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001176 int32_t left_mask = (left()->range() != NULL)
1177 ? left()->range()->Mask()
1178 : 0xffffffff;
1179 int32_t right_mask = (right()->range() != NULL)
1180 ? right()->range()->Mask()
1181 : 0xffffffff;
1182 int32_t result_mask = left_mask & right_mask;
1183 return (result_mask >= 0)
1184 ? new Range(0, result_mask)
1185 : HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001186}
1187
1188
1189Range* HBitOr::InferRange() {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001190 int32_t left_mask = (left()->range() != NULL)
1191 ? left()->range()->Mask()
1192 : 0xffffffff;
1193 int32_t right_mask = (right()->range() != NULL)
1194 ? right()->range()->Mask()
1195 : 0xffffffff;
1196 int32_t result_mask = left_mask | right_mask;
1197 return (result_mask >= 0)
1198 ? new Range(0, result_mask)
1199 : HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001200}
1201
1202
1203Range* HSar::InferRange() {
1204 if (right()->IsConstant()) {
1205 HConstant* c = HConstant::cast(right());
1206 if (c->HasInteger32Value()) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001207 Range* result = (left()->range() != NULL)
1208 ? left()->range()->Copy()
1209 : new Range();
1210 result->Sar(c->Integer32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001211 return result;
1212 }
1213 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001214 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001215}
1216
1217
1218Range* HShl::InferRange() {
1219 if (right()->IsConstant()) {
1220 HConstant* c = HConstant::cast(right());
1221 if (c->HasInteger32Value()) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001222 Range* result = (left()->range() != NULL)
1223 ? left()->range()->Copy()
1224 : new Range();
1225 result->Shl(c->Integer32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001226 return result;
1227 }
1228 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001229 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001230}
1231
1232
1233
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001234void HCompare::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001235 stream->Add(Token::Name(token()));
1236 stream->Add(" ");
1237 HBinaryOperation::PrintDataTo(stream);
1238}
1239
1240
1241void HCompare::SetInputRepresentation(Representation r) {
1242 input_representation_ = r;
1243 if (r.IsTagged()) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001244 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001245 ClearFlag(kUseGVN);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001246 } else if (r.IsDouble()) {
1247 SetFlag(kDeoptimizeOnUndefined);
1248 ClearAllSideEffects();
1249 SetFlag(kUseGVN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001250 } else {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001251 ClearAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001252 SetFlag(kUseGVN);
1253 }
1254}
1255
1256
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001257void HParameter::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001258 stream->Add("%u", index());
1259}
1260
1261
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001262void HLoadNamedField::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001263 object()->PrintNameTo(stream);
1264 stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1265}
1266
1267
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001268HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* object,
1269 ZoneMapList* types,
1270 Handle<String> name)
1271 : HUnaryOperation(object),
1272 types_(Min(types->length(), kMaxLoadPolymorphism)),
1273 name_(name),
1274 need_generic_(false) {
1275 set_representation(Representation::Tagged());
1276 SetFlag(kDependsOnMaps);
1277 for (int i = 0;
1278 i < types->length() && types_.length() < kMaxLoadPolymorphism;
1279 ++i) {
1280 Handle<Map> map = types->at(i);
1281 LookupResult lookup;
1282 map->LookupInDescriptors(NULL, *name, &lookup);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001283 if (lookup.IsProperty()) {
1284 switch (lookup.type()) {
1285 case FIELD: {
1286 int index = lookup.GetLocalFieldIndexFromMap(*map);
1287 if (index < 0) {
1288 SetFlag(kDependsOnInobjectFields);
1289 } else {
1290 SetFlag(kDependsOnBackingStoreFields);
1291 }
1292 types_.Add(types->at(i));
1293 break;
1294 }
1295 case CONSTANT_FUNCTION:
1296 types_.Add(types->at(i));
1297 break;
1298 default:
1299 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001300 }
1301 }
1302 }
1303
1304 if (types_.length() == types->length() && FLAG_deoptimize_uncommon_cases) {
1305 SetFlag(kUseGVN);
1306 } else {
1307 SetAllSideEffects();
1308 need_generic_ = true;
1309 }
1310}
1311
1312
1313bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
1314 HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
1315 if (types_.length() != other->types()->length()) return false;
1316 if (!name_.is_identical_to(other->name())) return false;
1317 if (need_generic_ != other->need_generic_) return false;
1318 for (int i = 0; i < types_.length(); i++) {
1319 bool found = false;
1320 for (int j = 0; j < types_.length(); j++) {
1321 if (types_.at(j).is_identical_to(other->types()->at(i))) {
1322 found = true;
1323 break;
1324 }
1325 }
1326 if (!found) return false;
1327 }
1328 return true;
1329}
1330
1331
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001332void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001333 object()->PrintNameTo(stream);
1334 stream->Add("[");
1335 key()->PrintNameTo(stream);
1336 stream->Add("]");
1337}
1338
1339
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001340bool HLoadKeyedFastElement::RequiresHoleCheck() const {
1341 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1342 HValue* use = it.value();
1343 if (!use->IsChange()) return true;
1344 }
1345 return false;
1346}
1347
1348
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001349void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
1350 object()->PrintNameTo(stream);
1351 stream->Add("[");
1352 key()->PrintNameTo(stream);
1353 stream->Add("]");
1354}
1355
1356
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001357void HLoadKeyedSpecializedArrayElement::PrintDataTo(
1358 StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001359 external_pointer()->PrintNameTo(stream);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001360 stream->Add(".");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001361 switch (elements_kind()) {
1362 case JSObject::EXTERNAL_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001363 stream->Add("byte");
1364 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001365 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001366 stream->Add("u_byte");
1367 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001368 case JSObject::EXTERNAL_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001369 stream->Add("short");
1370 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001371 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001372 stream->Add("u_short");
1373 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001374 case JSObject::EXTERNAL_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001375 stream->Add("int");
1376 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001377 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001378 stream->Add("u_int");
1379 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001380 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001381 stream->Add("float");
1382 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001383 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001384 stream->Add("double");
1385 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001386 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001387 stream->Add("pixel");
1388 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001389 case JSObject::FAST_ELEMENTS:
1390 case JSObject::FAST_DOUBLE_ELEMENTS:
1391 case JSObject::DICTIONARY_ELEMENTS:
1392 UNREACHABLE();
1393 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001394 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001395 stream->Add("[");
1396 key()->PrintNameTo(stream);
1397 stream->Add("]");
1398}
1399
1400
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001401void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001402 object()->PrintNameTo(stream);
1403 stream->Add(".");
1404 ASSERT(name()->IsString());
1405 stream->Add(*String::cast(*name())->ToCString());
1406 stream->Add(" = ");
1407 value()->PrintNameTo(stream);
1408}
1409
1410
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001411void HStoreNamedField::PrintDataTo(StringStream* stream) {
1412 object()->PrintNameTo(stream);
1413 stream->Add(".");
1414 ASSERT(name()->IsString());
1415 stream->Add(*String::cast(*name())->ToCString());
1416 stream->Add(" = ");
1417 value()->PrintNameTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001418 if (!transition().is_null()) {
1419 stream->Add(" (transition map %p)", *transition());
1420 }
1421}
1422
1423
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001424void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001425 object()->PrintNameTo(stream);
1426 stream->Add("[");
1427 key()->PrintNameTo(stream);
1428 stream->Add("] = ");
1429 value()->PrintNameTo(stream);
1430}
1431
1432
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001433void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
1434 object()->PrintNameTo(stream);
1435 stream->Add("[");
1436 key()->PrintNameTo(stream);
1437 stream->Add("] = ");
1438 value()->PrintNameTo(stream);
1439}
1440
1441
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001442void HStoreKeyedSpecializedArrayElement::PrintDataTo(
1443 StringStream* stream) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001444 external_pointer()->PrintNameTo(stream);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001445 stream->Add(".");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001446 switch (elements_kind()) {
1447 case JSObject::EXTERNAL_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001448 stream->Add("byte");
1449 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001450 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001451 stream->Add("u_byte");
1452 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001453 case JSObject::EXTERNAL_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001454 stream->Add("short");
1455 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001456 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001457 stream->Add("u_short");
1458 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001459 case JSObject::EXTERNAL_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001460 stream->Add("int");
1461 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001462 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001463 stream->Add("u_int");
1464 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001465 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001466 stream->Add("float");
1467 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001468 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001469 stream->Add("double");
1470 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001471 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001472 stream->Add("pixel");
1473 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001474 case JSObject::FAST_ELEMENTS:
1475 case JSObject::FAST_DOUBLE_ELEMENTS:
1476 case JSObject::DICTIONARY_ELEMENTS:
1477 UNREACHABLE();
1478 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001479 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001480 stream->Add("[");
1481 key()->PrintNameTo(stream);
1482 stream->Add("] = ");
1483 value()->PrintNameTo(stream);
1484}
1485
1486
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001487void HLoadGlobalCell::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001488 stream->Add("[%p]", *cell());
1489 if (check_hole_value()) stream->Add(" (deleteable/read-only)");
1490}
1491
1492
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001493void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) {
1494 stream->Add("%o ", *name());
1495}
1496
1497
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001498void HStoreGlobalCell::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001499 stream->Add("[%p] = ", *cell());
1500 value()->PrintNameTo(stream);
1501}
1502
1503
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001504void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
1505 stream->Add("%o = ", *name());
1506 value()->PrintNameTo(stream);
1507}
1508
1509
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001510void HLoadContextSlot::PrintDataTo(StringStream* stream) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001511 value()->PrintNameTo(stream);
1512 stream->Add("[%d]", slot_index());
1513}
1514
1515
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001516void HStoreContextSlot::PrintDataTo(StringStream* stream) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001517 context()->PrintNameTo(stream);
1518 stream->Add("[%d] = ", slot_index());
1519 value()->PrintNameTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001520}
1521
1522
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001523// Implementation of type inference and type conversions. Calculates
1524// the inferred type of this instruction based on the input operands.
1525
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001526HType HValue::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001527 return type_;
1528}
1529
1530
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001531HType HCheckMap::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001532 return value()->type();
1533}
1534
1535
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001536HType HCheckFunction::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001537 return value()->type();
1538}
1539
1540
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001541HType HCheckNonSmi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001542 // TODO(kasperl): Is there any way to signal that this isn't a smi?
1543 return HType::Tagged();
1544}
1545
1546
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001547HType HCheckSmi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001548 return HType::Smi();
1549}
1550
1551
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001552HType HPhi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001553 HType result = HType::Uninitialized();
1554 for (int i = 0; i < OperandCount(); ++i) {
1555 HType current = OperandAt(i)->type();
1556 result = result.Combine(current);
1557 }
1558 return result;
1559}
1560
1561
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001562HType HConstant::CalculateInferredType() {
danno@chromium.org160a7b02011-04-18 15:51:38 +00001563 return HType::TypeFromValue(handle_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001564}
1565
1566
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001567HType HCompare::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001568 return HType::Boolean();
1569}
1570
1571
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001572HType HCompareJSObjectEq::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001573 return HType::Boolean();
1574}
1575
1576
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001577HType HUnaryPredicate::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001578 return HType::Boolean();
1579}
1580
1581
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001582HType HInstanceOf::CalculateInferredType() {
1583 return HType::Boolean();
1584}
1585
1586
1587HType HDeleteProperty::CalculateInferredType() {
1588 return HType::Boolean();
1589}
1590
1591
1592HType HInstanceOfKnownGlobal::CalculateInferredType() {
1593 return HType::Boolean();
1594}
1595
1596
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001597HType HBitwiseBinaryOperation::CalculateInferredType() {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001598 return HType::TaggedNumber();
1599}
1600
1601
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001602HType HArithmeticBinaryOperation::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001603 return HType::TaggedNumber();
1604}
1605
1606
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001607HType HAdd::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001608 return HType::Tagged();
1609}
1610
1611
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001612HType HBitAnd::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001613 return HType::TaggedNumber();
1614}
1615
1616
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001617HType HBitXor::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001618 return HType::TaggedNumber();
1619}
1620
1621
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001622HType HBitOr::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001623 return HType::TaggedNumber();
1624}
1625
1626
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001627HType HBitNot::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001628 return HType::TaggedNumber();
1629}
1630
1631
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001632HType HUnaryMathOperation::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001633 return HType::TaggedNumber();
1634}
1635
1636
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001637HType HShl::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001638 return HType::TaggedNumber();
1639}
1640
1641
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001642HType HShr::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001643 return HType::TaggedNumber();
1644}
1645
1646
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001647HType HSar::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001648 return HType::TaggedNumber();
1649}
1650
1651
1652HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero(
1653 BitVector* visited) {
1654 visited->Add(id());
1655 if (representation().IsInteger32() &&
1656 !value()->representation().IsInteger32()) {
1657 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
1658 SetFlag(kBailoutOnMinusZero);
1659 }
1660 }
1661 if (RequiredInputRepresentation(0).IsInteger32() &&
1662 representation().IsInteger32()) {
1663 return value();
1664 }
1665 return NULL;
1666}
1667
1668
1669
1670HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1671 visited->Add(id());
1672 if (from().IsInteger32()) return NULL;
1673 if (CanTruncateToInt32()) return NULL;
1674 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
1675 SetFlag(kBailoutOnMinusZero);
1676 }
1677 ASSERT(!from().IsInteger32() || !to().IsInteger32());
1678 return NULL;
1679}
1680
1681
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001682HValue* HForceRepresentation::EnsureAndPropagateNotMinusZero(
1683 BitVector* visited) {
1684 visited->Add(id());
1685 return value();
1686}
1687
1688
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001689HValue* HMod::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1690 visited->Add(id());
1691 if (range() == NULL || range()->CanBeMinusZero()) {
1692 SetFlag(kBailoutOnMinusZero);
1693 return left();
1694 }
1695 return NULL;
1696}
1697
1698
1699HValue* HDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1700 visited->Add(id());
1701 if (range() == NULL || range()->CanBeMinusZero()) {
1702 SetFlag(kBailoutOnMinusZero);
1703 }
1704 return NULL;
1705}
1706
1707
1708HValue* HMul::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1709 visited->Add(id());
1710 if (range() == NULL || range()->CanBeMinusZero()) {
1711 SetFlag(kBailoutOnMinusZero);
1712 }
1713 return NULL;
1714}
1715
1716
1717HValue* HSub::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1718 visited->Add(id());
1719 // Propagate to the left argument. If the left argument cannot be -0, then
1720 // the result of the add operation cannot be either.
1721 if (range() == NULL || range()->CanBeMinusZero()) {
1722 return left();
1723 }
1724 return NULL;
1725}
1726
1727
1728HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1729 visited->Add(id());
1730 // Propagate to the left argument. If the left argument cannot be -0, then
1731 // the result of the sub operation cannot be either.
1732 if (range() == NULL || range()->CanBeMinusZero()) {
1733 return left();
1734 }
1735 return NULL;
1736}
1737
1738
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001739void HIn::PrintDataTo(StringStream* stream) {
1740 key()->PrintNameTo(stream);
1741 stream->Add(" ");
1742 object()->PrintNameTo(stream);
1743}
1744
1745
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001746// Node-specific verification code is only included in debug mode.
1747#ifdef DEBUG
1748
ager@chromium.org378b34e2011-01-28 08:04:38 +00001749void HPhi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001750 ASSERT(OperandCount() == block()->predecessors()->length());
1751 for (int i = 0; i < OperandCount(); ++i) {
1752 HValue* value = OperandAt(i);
1753 HBasicBlock* defining_block = value->block();
1754 HBasicBlock* predecessor_block = block()->predecessors()->at(i);
1755 ASSERT(defining_block == predecessor_block ||
1756 defining_block->Dominates(predecessor_block));
1757 }
1758}
1759
1760
ager@chromium.org378b34e2011-01-28 08:04:38 +00001761void HSimulate::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001762 HInstruction::Verify();
1763 ASSERT(HasAstId());
1764}
1765
1766
ager@chromium.org378b34e2011-01-28 08:04:38 +00001767void HBoundsCheck::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001768 HInstruction::Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001769}
1770
1771
ager@chromium.org378b34e2011-01-28 08:04:38 +00001772void HCheckSmi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001773 HInstruction::Verify();
1774 ASSERT(HasNoUses());
1775}
1776
1777
ager@chromium.org378b34e2011-01-28 08:04:38 +00001778void HCheckNonSmi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001779 HInstruction::Verify();
1780 ASSERT(HasNoUses());
1781}
1782
1783
ager@chromium.org378b34e2011-01-28 08:04:38 +00001784void HCheckInstanceType::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001785 HInstruction::Verify();
1786 ASSERT(HasNoUses());
1787}
1788
1789
ager@chromium.org378b34e2011-01-28 08:04:38 +00001790void HCheckMap::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001791 HInstruction::Verify();
1792 ASSERT(HasNoUses());
1793}
1794
1795
ager@chromium.org378b34e2011-01-28 08:04:38 +00001796void HCheckFunction::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001797 HInstruction::Verify();
1798 ASSERT(HasNoUses());
1799}
1800
1801
ager@chromium.org378b34e2011-01-28 08:04:38 +00001802void HCheckPrototypeMaps::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001803 HInstruction::Verify();
1804 ASSERT(HasNoUses());
1805}
1806
1807#endif
1808
1809} } // namespace v8::internal