blob: 2be2a032574b6bf9af1f8560e19fe95d1694bab7 [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
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000672void HClassOfTestAndBranch::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
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000750void HHasInstanceTypeAndBranch::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
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000771void HTypeofIsAndBranch::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
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000787HValue* HCheckInstanceType::Canonicalize() {
788 if (check_ == IS_STRING &&
789 !value()->type().IsUninitialized() &&
790 value()->type().IsString()) {
791 return NULL;
792 }
793 if (check_ == IS_SYMBOL &&
794 value()->IsConstant() &&
795 HConstant::cast(value())->handle()->IsSymbol()) {
796 return NULL;
797 }
798 return this;
799}
800
801
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000802void HCheckInstanceType::GetCheckInterval(InstanceType* first,
803 InstanceType* last) {
804 ASSERT(is_interval_check());
805 switch (check_) {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000806 case IS_SPEC_OBJECT:
807 *first = FIRST_SPEC_OBJECT_TYPE;
808 *last = LAST_SPEC_OBJECT_TYPE;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000809 return;
810 case IS_JS_ARRAY:
811 *first = *last = JS_ARRAY_TYPE;
812 return;
813 default:
814 UNREACHABLE();
815 }
816}
817
818
819void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
820 ASSERT(!is_interval_check());
821 switch (check_) {
822 case IS_STRING:
823 *mask = kIsNotStringMask;
824 *tag = kStringTag;
825 return;
826 case IS_SYMBOL:
827 *mask = kIsSymbolMask;
828 *tag = kSymbolTag;
829 return;
830 default:
831 UNREACHABLE();
832 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000833}
834
835
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000836void HCheckMap::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000837 value()->PrintNameTo(stream);
838 stream->Add(" %p", *map());
839}
840
841
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000842void HCheckFunction::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000843 value()->PrintNameTo(stream);
844 stream->Add(" %p", *target());
845}
846
847
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000848void HCallStub::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000849 stream->Add("%s ",
850 CodeStub::MajorName(major_key_, false));
851 HUnaryCall::PrintDataTo(stream);
852}
853
854
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000855void HInstanceOf::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000856 left()->PrintNameTo(stream);
857 stream->Add(" ");
858 right()->PrintNameTo(stream);
859 stream->Add(" ");
860 context()->PrintNameTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000861}
862
863
864Range* HValue::InferRange() {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000865 if (representation().IsTagged()) {
866 // Tagged values are always in int32 range when converted to integer,
867 // but they can contain -0.
868 Range* result = new Range();
869 result->set_can_be_minus_zero(true);
870 return result;
871 } else if (representation().IsNone()) {
872 return NULL;
873 } else {
874 // Untagged integer32 cannot be -0 and we don't compute ranges for
875 // untagged doubles.
876 return new Range();
877 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000878}
879
880
881Range* HConstant::InferRange() {
882 if (has_int32_value_) {
883 Range* result = new Range(int32_value_, int32_value_);
884 result->set_can_be_minus_zero(false);
885 return result;
886 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000887 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000888}
889
890
891Range* HPhi::InferRange() {
892 if (representation().IsInteger32()) {
893 if (block()->IsLoopHeader()) {
894 Range* range = new Range(kMinInt, kMaxInt);
895 return range;
896 } else {
897 Range* range = OperandAt(0)->range()->Copy();
898 for (int i = 1; i < OperandCount(); ++i) {
899 range->Union(OperandAt(i)->range());
900 }
901 return range;
902 }
903 } else {
904 return HValue::InferRange();
905 }
906}
907
908
909Range* HAdd::InferRange() {
910 if (representation().IsInteger32()) {
911 Range* a = left()->range();
912 Range* b = right()->range();
913 Range* res = a->Copy();
914 if (!res->AddAndCheckOverflow(b)) {
915 ClearFlag(kCanOverflow);
916 }
917 bool m0 = a->CanBeMinusZero() && b->CanBeMinusZero();
918 res->set_can_be_minus_zero(m0);
919 return res;
920 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000921 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000922 }
923}
924
925
926Range* HSub::InferRange() {
927 if (representation().IsInteger32()) {
928 Range* a = left()->range();
929 Range* b = right()->range();
930 Range* res = a->Copy();
931 if (!res->SubAndCheckOverflow(b)) {
932 ClearFlag(kCanOverflow);
933 }
934 res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
935 return res;
936 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000937 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000938 }
939}
940
941
942Range* HMul::InferRange() {
943 if (representation().IsInteger32()) {
944 Range* a = left()->range();
945 Range* b = right()->range();
946 Range* res = a->Copy();
947 if (!res->MulAndCheckOverflow(b)) {
948 ClearFlag(kCanOverflow);
949 }
950 bool m0 = (a->CanBeZero() && b->CanBeNegative()) ||
951 (a->CanBeNegative() && b->CanBeZero());
952 res->set_can_be_minus_zero(m0);
953 return res;
954 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000955 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000956 }
957}
958
959
960Range* HDiv::InferRange() {
961 if (representation().IsInteger32()) {
962 Range* result = new Range();
963 if (left()->range()->CanBeMinusZero()) {
964 result->set_can_be_minus_zero(true);
965 }
966
967 if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) {
968 result->set_can_be_minus_zero(true);
969 }
970
971 if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
972 SetFlag(HValue::kCanOverflow);
973 }
974
975 if (!right()->range()->CanBeZero()) {
976 ClearFlag(HValue::kCanBeDivByZero);
977 }
978 return result;
979 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000980 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000981 }
982}
983
984
985Range* HMod::InferRange() {
986 if (representation().IsInteger32()) {
987 Range* a = left()->range();
988 Range* result = new Range();
989 if (a->CanBeMinusZero() || a->CanBeNegative()) {
990 result->set_can_be_minus_zero(true);
991 }
992 if (!right()->range()->CanBeZero()) {
993 ClearFlag(HValue::kCanBeDivByZero);
994 }
995 return result;
996 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000997 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000998 }
999}
1000
1001
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001002void HPhi::PrintTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001003 stream->Add("[");
1004 for (int i = 0; i < OperandCount(); ++i) {
1005 HValue* value = OperandAt(i);
1006 stream->Add(" ");
1007 value->PrintNameTo(stream);
1008 stream->Add(" ");
1009 }
1010 stream->Add(" uses%d_%di_%dd_%dt]",
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001011 UseCount(),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001012 int32_non_phi_uses() + int32_indirect_uses(),
1013 double_non_phi_uses() + double_indirect_uses(),
1014 tagged_non_phi_uses() + tagged_indirect_uses());
1015}
1016
1017
1018void HPhi::AddInput(HValue* value) {
1019 inputs_.Add(NULL);
1020 SetOperandAt(OperandCount() - 1, value);
1021 // Mark phis that may have 'arguments' directly or indirectly as an operand.
1022 if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) {
1023 SetFlag(kIsArguments);
1024 }
1025}
1026
1027
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001028bool HPhi::HasRealUses() {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001029 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1030 if (!it.value()->IsPhi()) return true;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001031 }
1032 return false;
1033}
1034
1035
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001036HValue* HPhi::GetRedundantReplacement() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001037 HValue* candidate = NULL;
1038 int count = OperandCount();
1039 int position = 0;
1040 while (position < count && candidate == NULL) {
1041 HValue* current = OperandAt(position++);
1042 if (current != this) candidate = current;
1043 }
1044 while (position < count) {
1045 HValue* current = OperandAt(position++);
1046 if (current != this && current != candidate) return NULL;
1047 }
1048 ASSERT(candidate != this);
1049 return candidate;
1050}
1051
1052
1053void HPhi::DeleteFromGraph() {
1054 ASSERT(block() != NULL);
1055 block()->RemovePhi(this);
1056 ASSERT(block() == NULL);
1057}
1058
1059
1060void HPhi::InitRealUses(int phi_id) {
1061 // Initialize real uses.
1062 phi_id_ = phi_id;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001063 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1064 HValue* value = it.value();
1065 if (!value->IsPhi()) {
1066 Representation rep = value->RequiredInputRepresentation(it.index());
1067 ++non_phi_uses_[rep.kind()];
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001068 }
1069 }
1070}
1071
1072
1073void HPhi::AddNonPhiUsesFrom(HPhi* other) {
1074 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1075 indirect_uses_[i] += other->non_phi_uses_[i];
1076 }
1077}
1078
1079
1080void HPhi::AddIndirectUsesTo(int* dest) {
1081 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1082 dest[i] += indirect_uses_[i];
1083 }
1084}
1085
1086
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001087void HSimulate::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001088 stream->Add("id=%d ", ast_id());
1089 if (pop_count_ > 0) stream->Add("pop %d", pop_count_);
1090 if (values_.length() > 0) {
1091 if (pop_count_ > 0) stream->Add(" /");
1092 for (int i = 0; i < values_.length(); ++i) {
1093 if (!HasAssignedIndexAt(i)) {
1094 stream->Add(" push ");
1095 } else {
1096 stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
1097 }
1098 values_[i]->PrintNameTo(stream);
1099 }
1100 }
1101}
1102
1103
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00001104void HDeoptimize::PrintDataTo(StringStream* stream) {
1105 if (OperandCount() == 0) return;
1106 OperandAt(0)->PrintNameTo(stream);
1107 for (int i = 1; i < OperandCount(); ++i) {
1108 stream->Add(" ");
1109 OperandAt(i)->PrintNameTo(stream);
1110 }
1111}
1112
1113
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001114void HEnterInlined::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001115 SmartPointer<char> name = function()->debug_name()->ToCString();
1116 stream->Add("%s, id=%d", *name, function()->id());
1117}
1118
1119
1120HConstant::HConstant(Handle<Object> handle, Representation r)
1121 : handle_(handle),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001122 has_int32_value_(false),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001123 has_double_value_(false),
danno@chromium.org160a7b02011-04-18 15:51:38 +00001124 int32_value_(0),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001125 double_value_(0) {
1126 set_representation(r);
1127 SetFlag(kUseGVN);
1128 if (handle_->IsNumber()) {
1129 double n = handle_->Number();
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001130 double roundtrip_value = static_cast<double>(static_cast<int32_t>(n));
1131 has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001132 if (has_int32_value_) int32_value_ = static_cast<int32_t>(n);
1133 double_value_ = n;
1134 has_double_value_ = true;
1135 }
1136}
1137
1138
1139HConstant* HConstant::CopyToRepresentation(Representation r) const {
1140 if (r.IsInteger32() && !has_int32_value_) return NULL;
1141 if (r.IsDouble() && !has_double_value_) return NULL;
1142 return new HConstant(handle_, r);
1143}
1144
1145
1146HConstant* HConstant::CopyToTruncatedInt32() const {
1147 if (!has_double_value_) return NULL;
1148 int32_t truncated = NumberToInt32(*handle_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001149 return new HConstant(FACTORY->NewNumberFromInt(truncated),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001150 Representation::Integer32());
1151}
1152
1153
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001154bool HConstant::ToBoolean() const {
1155 // Converts the constant's boolean value according to
1156 // ECMAScript section 9.2 ToBoolean conversion.
1157 if (HasInteger32Value()) return Integer32Value() != 0;
1158 if (HasDoubleValue()) {
1159 double v = DoubleValue();
1160 return v != 0 && !isnan(v);
1161 }
1162 if (handle()->IsTrue()) return true;
1163 if (handle()->IsFalse()) return false;
1164 if (handle()->IsUndefined()) return false;
1165 if (handle()->IsNull()) return false;
1166 if (handle()->IsString() &&
1167 String::cast(*handle())->length() == 0) return false;
1168 return true;
1169}
1170
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001171void HConstant::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001172 handle()->ShortPrint(stream);
1173}
1174
1175
1176bool HArrayLiteral::IsCopyOnWrite() const {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001177 return constant_elements()->map() == HEAP->fixed_cow_array_map();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001178}
1179
1180
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001181void HBinaryOperation::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001182 left()->PrintNameTo(stream);
1183 stream->Add(" ");
1184 right()->PrintNameTo(stream);
1185 if (CheckFlag(kCanOverflow)) stream->Add(" !");
1186 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1187}
1188
1189
1190Range* HBitAnd::InferRange() {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001191 int32_t left_mask = (left()->range() != NULL)
1192 ? left()->range()->Mask()
1193 : 0xffffffff;
1194 int32_t right_mask = (right()->range() != NULL)
1195 ? right()->range()->Mask()
1196 : 0xffffffff;
1197 int32_t result_mask = left_mask & right_mask;
1198 return (result_mask >= 0)
1199 ? new Range(0, result_mask)
1200 : HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001201}
1202
1203
1204Range* HBitOr::InferRange() {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001205 int32_t left_mask = (left()->range() != NULL)
1206 ? left()->range()->Mask()
1207 : 0xffffffff;
1208 int32_t right_mask = (right()->range() != NULL)
1209 ? right()->range()->Mask()
1210 : 0xffffffff;
1211 int32_t result_mask = left_mask | right_mask;
1212 return (result_mask >= 0)
1213 ? new Range(0, result_mask)
1214 : HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001215}
1216
1217
1218Range* HSar::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->Sar(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
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001233Range* HShr::InferRange() {
1234 if (right()->IsConstant()) {
1235 HConstant* c = HConstant::cast(right());
1236 if (c->HasInteger32Value()) {
1237 int shift_count = c->Integer32Value() & 0x1f;
1238 if (left()->range()->CanBeNegative()) {
1239 // Only compute bounds if the result always fits into an int32.
1240 return (shift_count >= 1)
1241 ? new Range(0, static_cast<uint32_t>(0xffffffff) >> shift_count)
1242 : new Range();
1243 } else {
1244 // For positive inputs we can use the >> operator.
1245 Range* result = (left()->range() != NULL)
1246 ? left()->range()->Copy()
1247 : new Range();
1248 result->Sar(c->Integer32Value());
1249 return result;
1250 }
1251 }
1252 }
1253 return HValue::InferRange();
1254}
1255
1256
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001257Range* HShl::InferRange() {
1258 if (right()->IsConstant()) {
1259 HConstant* c = HConstant::cast(right());
1260 if (c->HasInteger32Value()) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001261 Range* result = (left()->range() != NULL)
1262 ? left()->range()->Copy()
1263 : new Range();
1264 result->Shl(c->Integer32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001265 return result;
1266 }
1267 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001268 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001269}
1270
1271
1272
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001273void HCompareGeneric::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001274 stream->Add(Token::Name(token()));
1275 stream->Add(" ");
1276 HBinaryOperation::PrintDataTo(stream);
1277}
1278
1279
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001280void HCompareIDAndBranch::PrintDataTo(StringStream* stream) {
1281 stream->Add(Token::Name(token()));
1282 stream->Add(" ");
1283 left()->PrintNameTo(stream);
1284 stream->Add(" ");
1285 right()->PrintNameTo(stream);
1286}
1287
1288
1289void HCompareIDAndBranch::SetInputRepresentation(Representation r) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001290 input_representation_ = r;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001291 if (r.IsDouble()) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001292 SetFlag(kDeoptimizeOnUndefined);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001293 } else {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001294 ASSERT(r.IsInteger32());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001295 }
1296}
1297
1298
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001299void HParameter::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001300 stream->Add("%u", index());
1301}
1302
1303
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001304void HLoadNamedField::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001305 object()->PrintNameTo(stream);
1306 stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1307}
1308
1309
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001310HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
1311 HValue* object,
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001312 ZoneMapList* types,
1313 Handle<String> name)
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001314 : types_(Min(types->length(), kMaxLoadPolymorphism)),
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001315 name_(name),
1316 need_generic_(false) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001317 SetOperandAt(0, context);
1318 SetOperandAt(1, object);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001319 set_representation(Representation::Tagged());
1320 SetFlag(kDependsOnMaps);
1321 for (int i = 0;
1322 i < types->length() && types_.length() < kMaxLoadPolymorphism;
1323 ++i) {
1324 Handle<Map> map = types->at(i);
1325 LookupResult lookup;
1326 map->LookupInDescriptors(NULL, *name, &lookup);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001327 if (lookup.IsProperty()) {
1328 switch (lookup.type()) {
1329 case FIELD: {
1330 int index = lookup.GetLocalFieldIndexFromMap(*map);
1331 if (index < 0) {
1332 SetFlag(kDependsOnInobjectFields);
1333 } else {
1334 SetFlag(kDependsOnBackingStoreFields);
1335 }
1336 types_.Add(types->at(i));
1337 break;
1338 }
1339 case CONSTANT_FUNCTION:
1340 types_.Add(types->at(i));
1341 break;
1342 default:
1343 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001344 }
1345 }
1346 }
1347
1348 if (types_.length() == types->length() && FLAG_deoptimize_uncommon_cases) {
1349 SetFlag(kUseGVN);
1350 } else {
1351 SetAllSideEffects();
1352 need_generic_ = true;
1353 }
1354}
1355
1356
1357bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
1358 HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
1359 if (types_.length() != other->types()->length()) return false;
1360 if (!name_.is_identical_to(other->name())) return false;
1361 if (need_generic_ != other->need_generic_) return false;
1362 for (int i = 0; i < types_.length(); i++) {
1363 bool found = false;
1364 for (int j = 0; j < types_.length(); j++) {
1365 if (types_.at(j).is_identical_to(other->types()->at(i))) {
1366 found = true;
1367 break;
1368 }
1369 }
1370 if (!found) return false;
1371 }
1372 return true;
1373}
1374
1375
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001376void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001377 object()->PrintNameTo(stream);
1378 stream->Add("[");
1379 key()->PrintNameTo(stream);
1380 stream->Add("]");
1381}
1382
1383
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001384bool HLoadKeyedFastElement::RequiresHoleCheck() const {
1385 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1386 HValue* use = it.value();
1387 if (!use->IsChange()) return true;
1388 }
1389 return false;
1390}
1391
1392
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001393void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
1394 elements()->PrintNameTo(stream);
1395 stream->Add("[");
1396 key()->PrintNameTo(stream);
1397 stream->Add("]");
1398}
1399
1400
1401bool HLoadKeyedFastDoubleElement::RequiresHoleCheck() const {
1402 return true;
1403}
1404
1405
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001406void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
1407 object()->PrintNameTo(stream);
1408 stream->Add("[");
1409 key()->PrintNameTo(stream);
1410 stream->Add("]");
1411}
1412
1413
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001414void HLoadKeyedSpecializedArrayElement::PrintDataTo(
1415 StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001416 external_pointer()->PrintNameTo(stream);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001417 stream->Add(".");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001418 switch (elements_kind()) {
1419 case JSObject::EXTERNAL_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001420 stream->Add("byte");
1421 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001422 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001423 stream->Add("u_byte");
1424 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001425 case JSObject::EXTERNAL_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001426 stream->Add("short");
1427 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001428 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001429 stream->Add("u_short");
1430 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001431 case JSObject::EXTERNAL_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001432 stream->Add("int");
1433 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001434 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001435 stream->Add("u_int");
1436 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001437 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001438 stream->Add("float");
1439 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001440 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001441 stream->Add("double");
1442 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001443 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001444 stream->Add("pixel");
1445 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001446 case JSObject::FAST_ELEMENTS:
1447 case JSObject::FAST_DOUBLE_ELEMENTS:
1448 case JSObject::DICTIONARY_ELEMENTS:
whesse@chromium.org7b260152011-06-20 15:33:18 +00001449 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001450 UNREACHABLE();
1451 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001452 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001453 stream->Add("[");
1454 key()->PrintNameTo(stream);
1455 stream->Add("]");
1456}
1457
1458
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001459void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001460 object()->PrintNameTo(stream);
1461 stream->Add(".");
1462 ASSERT(name()->IsString());
1463 stream->Add(*String::cast(*name())->ToCString());
1464 stream->Add(" = ");
1465 value()->PrintNameTo(stream);
1466}
1467
1468
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001469void HStoreNamedField::PrintDataTo(StringStream* stream) {
1470 object()->PrintNameTo(stream);
1471 stream->Add(".");
1472 ASSERT(name()->IsString());
1473 stream->Add(*String::cast(*name())->ToCString());
1474 stream->Add(" = ");
1475 value()->PrintNameTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001476 if (!transition().is_null()) {
1477 stream->Add(" (transition map %p)", *transition());
1478 }
1479}
1480
1481
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001482void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001483 object()->PrintNameTo(stream);
1484 stream->Add("[");
1485 key()->PrintNameTo(stream);
1486 stream->Add("] = ");
1487 value()->PrintNameTo(stream);
1488}
1489
1490
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001491void HStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
1492 elements()->PrintNameTo(stream);
1493 stream->Add("[");
1494 key()->PrintNameTo(stream);
1495 stream->Add("] = ");
1496 value()->PrintNameTo(stream);
1497}
1498
1499
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001500void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
1501 object()->PrintNameTo(stream);
1502 stream->Add("[");
1503 key()->PrintNameTo(stream);
1504 stream->Add("] = ");
1505 value()->PrintNameTo(stream);
1506}
1507
1508
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001509void HStoreKeyedSpecializedArrayElement::PrintDataTo(
1510 StringStream* stream) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001511 external_pointer()->PrintNameTo(stream);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001512 stream->Add(".");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001513 switch (elements_kind()) {
1514 case JSObject::EXTERNAL_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001515 stream->Add("byte");
1516 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001517 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001518 stream->Add("u_byte");
1519 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001520 case JSObject::EXTERNAL_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001521 stream->Add("short");
1522 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001523 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001524 stream->Add("u_short");
1525 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001526 case JSObject::EXTERNAL_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001527 stream->Add("int");
1528 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001529 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001530 stream->Add("u_int");
1531 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001532 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001533 stream->Add("float");
1534 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001535 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001536 stream->Add("double");
1537 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001538 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001539 stream->Add("pixel");
1540 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001541 case JSObject::FAST_ELEMENTS:
1542 case JSObject::FAST_DOUBLE_ELEMENTS:
1543 case JSObject::DICTIONARY_ELEMENTS:
whesse@chromium.org7b260152011-06-20 15:33:18 +00001544 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001545 UNREACHABLE();
1546 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001547 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001548 stream->Add("[");
1549 key()->PrintNameTo(stream);
1550 stream->Add("] = ");
1551 value()->PrintNameTo(stream);
1552}
1553
1554
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001555void HLoadGlobalCell::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001556 stream->Add("[%p]", *cell());
1557 if (check_hole_value()) stream->Add(" (deleteable/read-only)");
1558}
1559
1560
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001561void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) {
1562 stream->Add("%o ", *name());
1563}
1564
1565
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001566void HStoreGlobalCell::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001567 stream->Add("[%p] = ", *cell());
1568 value()->PrintNameTo(stream);
1569}
1570
1571
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001572void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
1573 stream->Add("%o = ", *name());
1574 value()->PrintNameTo(stream);
1575}
1576
1577
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001578void HLoadContextSlot::PrintDataTo(StringStream* stream) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001579 value()->PrintNameTo(stream);
1580 stream->Add("[%d]", slot_index());
1581}
1582
1583
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001584void HStoreContextSlot::PrintDataTo(StringStream* stream) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001585 context()->PrintNameTo(stream);
1586 stream->Add("[%d] = ", slot_index());
1587 value()->PrintNameTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001588}
1589
1590
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001591// Implementation of type inference and type conversions. Calculates
1592// the inferred type of this instruction based on the input operands.
1593
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001594HType HValue::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001595 return type_;
1596}
1597
1598
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001599HType HCheckMap::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001600 return value()->type();
1601}
1602
1603
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001604HType HCheckFunction::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001605 return value()->type();
1606}
1607
1608
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001609HType HCheckNonSmi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001610 // TODO(kasperl): Is there any way to signal that this isn't a smi?
1611 return HType::Tagged();
1612}
1613
1614
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001615HType HCheckSmi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001616 return HType::Smi();
1617}
1618
1619
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001620HType HPhi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001621 HType result = HType::Uninitialized();
1622 for (int i = 0; i < OperandCount(); ++i) {
1623 HType current = OperandAt(i)->type();
1624 result = result.Combine(current);
1625 }
1626 return result;
1627}
1628
1629
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001630HType HConstant::CalculateInferredType() {
danno@chromium.org160a7b02011-04-18 15:51:38 +00001631 return HType::TypeFromValue(handle_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001632}
1633
1634
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001635HType HCompareGeneric::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001636 return HType::Boolean();
1637}
1638
1639
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001640HType HInstanceOf::CalculateInferredType() {
1641 return HType::Boolean();
1642}
1643
1644
1645HType HDeleteProperty::CalculateInferredType() {
1646 return HType::Boolean();
1647}
1648
1649
1650HType HInstanceOfKnownGlobal::CalculateInferredType() {
1651 return HType::Boolean();
1652}
1653
1654
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001655HType HBitwiseBinaryOperation::CalculateInferredType() {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001656 return HType::TaggedNumber();
1657}
1658
1659
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001660HType HArithmeticBinaryOperation::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001661 return HType::TaggedNumber();
1662}
1663
1664
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001665HType HAdd::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001666 return HType::Tagged();
1667}
1668
1669
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001670HType HBitAnd::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001671 return HType::TaggedNumber();
1672}
1673
1674
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001675HType HBitXor::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001676 return HType::TaggedNumber();
1677}
1678
1679
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001680HType HBitOr::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001681 return HType::TaggedNumber();
1682}
1683
1684
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001685HType HBitNot::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001686 return HType::TaggedNumber();
1687}
1688
1689
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001690HType HUnaryMathOperation::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001691 return HType::TaggedNumber();
1692}
1693
1694
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001695HType HShl::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001696 return HType::TaggedNumber();
1697}
1698
1699
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001700HType HShr::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001701 return HType::TaggedNumber();
1702}
1703
1704
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001705HType HSar::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001706 return HType::TaggedNumber();
1707}
1708
1709
1710HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero(
1711 BitVector* visited) {
1712 visited->Add(id());
1713 if (representation().IsInteger32() &&
1714 !value()->representation().IsInteger32()) {
1715 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
1716 SetFlag(kBailoutOnMinusZero);
1717 }
1718 }
1719 if (RequiredInputRepresentation(0).IsInteger32() &&
1720 representation().IsInteger32()) {
1721 return value();
1722 }
1723 return NULL;
1724}
1725
1726
1727
1728HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1729 visited->Add(id());
1730 if (from().IsInteger32()) return NULL;
1731 if (CanTruncateToInt32()) return NULL;
1732 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
1733 SetFlag(kBailoutOnMinusZero);
1734 }
1735 ASSERT(!from().IsInteger32() || !to().IsInteger32());
1736 return NULL;
1737}
1738
1739
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001740HValue* HForceRepresentation::EnsureAndPropagateNotMinusZero(
1741 BitVector* visited) {
1742 visited->Add(id());
1743 return value();
1744}
1745
1746
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001747HValue* HMod::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1748 visited->Add(id());
1749 if (range() == NULL || range()->CanBeMinusZero()) {
1750 SetFlag(kBailoutOnMinusZero);
1751 return left();
1752 }
1753 return NULL;
1754}
1755
1756
1757HValue* HDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1758 visited->Add(id());
1759 if (range() == NULL || range()->CanBeMinusZero()) {
1760 SetFlag(kBailoutOnMinusZero);
1761 }
1762 return NULL;
1763}
1764
1765
1766HValue* HMul::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1767 visited->Add(id());
1768 if (range() == NULL || range()->CanBeMinusZero()) {
1769 SetFlag(kBailoutOnMinusZero);
1770 }
1771 return NULL;
1772}
1773
1774
1775HValue* HSub::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1776 visited->Add(id());
1777 // Propagate to the left argument. If the left argument cannot be -0, then
1778 // the result of the add operation cannot be either.
1779 if (range() == NULL || range()->CanBeMinusZero()) {
1780 return left();
1781 }
1782 return NULL;
1783}
1784
1785
1786HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1787 visited->Add(id());
1788 // Propagate to the left argument. If the left argument cannot be -0, then
1789 // the result of the sub operation cannot be either.
1790 if (range() == NULL || range()->CanBeMinusZero()) {
1791 return left();
1792 }
1793 return NULL;
1794}
1795
1796
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001797void HIn::PrintDataTo(StringStream* stream) {
1798 key()->PrintNameTo(stream);
1799 stream->Add(" ");
1800 object()->PrintNameTo(stream);
1801}
1802
1803
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001804// Node-specific verification code is only included in debug mode.
1805#ifdef DEBUG
1806
ager@chromium.org378b34e2011-01-28 08:04:38 +00001807void HPhi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001808 ASSERT(OperandCount() == block()->predecessors()->length());
1809 for (int i = 0; i < OperandCount(); ++i) {
1810 HValue* value = OperandAt(i);
1811 HBasicBlock* defining_block = value->block();
1812 HBasicBlock* predecessor_block = block()->predecessors()->at(i);
1813 ASSERT(defining_block == predecessor_block ||
1814 defining_block->Dominates(predecessor_block));
1815 }
1816}
1817
1818
ager@chromium.org378b34e2011-01-28 08:04:38 +00001819void HSimulate::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001820 HInstruction::Verify();
1821 ASSERT(HasAstId());
1822}
1823
1824
ager@chromium.org378b34e2011-01-28 08:04:38 +00001825void HCheckSmi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001826 HInstruction::Verify();
1827 ASSERT(HasNoUses());
1828}
1829
1830
ager@chromium.org378b34e2011-01-28 08:04:38 +00001831void HCheckNonSmi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001832 HInstruction::Verify();
1833 ASSERT(HasNoUses());
1834}
1835
1836
ager@chromium.org378b34e2011-01-28 08:04:38 +00001837void HCheckFunction::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001838 HInstruction::Verify();
1839 ASSERT(HasNoUses());
1840}
1841
1842
ager@chromium.org378b34e2011-01-28 08:04:38 +00001843void HCheckPrototypeMaps::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001844 HInstruction::Verify();
1845 ASSERT(HasNoUses());
1846}
1847
1848#endif
1849
1850} } // namespace v8::internal