blob: 71c59b5d9ecf0a4c998a572ad4af6d15e793ef17 [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
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000638void HBoundsCheck::PrintDataTo(StringStream* stream) {
639 index()->PrintNameTo(stream);
640 stream->Add(" ");
641 length()->PrintNameTo(stream);
642}
643
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000644void HCallConstantFunction::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000645 if (IsApplyFunction()) {
646 stream->Add("optimized apply ");
647 } else {
648 stream->Add("%o ", function()->shared()->DebugName());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000649 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000650 stream->Add("#%d", argument_count());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000651}
652
653
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000654void HCallNamed::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 HCallGlobal::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000661 stream->Add("%o ", *name());
662 HUnaryCall::PrintDataTo(stream);
663}
664
665
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000666void HCallKnownGlobal::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000667 stream->Add("o ", target()->shared()->DebugName());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000668 stream->Add("#%d", argument_count());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000669}
670
671
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000672void HCallRuntime::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000673 stream->Add("%o ", *name());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000674 stream->Add("#%d", argument_count());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000675}
676
677
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000678void HClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000679 stream->Add("class_of_test(");
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000680 value()->PrintNameTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000681 stream->Add(", \"%o\")", *class_name());
682}
683
684
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000685void HAccessArgumentsAt::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000686 arguments()->PrintNameTo(stream);
687 stream->Add("[");
688 index()->PrintNameTo(stream);
689 stream->Add("], length ");
690 length()->PrintNameTo(stream);
691}
692
693
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000694void HControlInstruction::PrintDataTo(StringStream* stream) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000695 stream->Add(" goto (");
696 bool first_block = true;
697 for (HSuccessorIterator it(this); !it.Done(); it.Advance()) {
698 stream->Add(first_block ? "B%d" : ", B%d", it.Current()->block_id());
699 first_block = false;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000700 }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000701 stream->Add(")");
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000702}
703
704
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000705void HUnaryControlInstruction::PrintDataTo(StringStream* stream) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000706 value()->PrintNameTo(stream);
707 HControlInstruction::PrintDataTo(stream);
708}
709
710
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000711void HReturn::PrintDataTo(StringStream* stream) {
712 value()->PrintNameTo(stream);
713}
714
715
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000716void HCompareMap::PrintDataTo(StringStream* stream) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000717 value()->PrintNameTo(stream);
718 stream->Add(" (%p)", *map());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000719 HControlInstruction::PrintDataTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000720}
721
722
723const char* HUnaryMathOperation::OpName() const {
724 switch (op()) {
725 case kMathFloor: return "floor";
726 case kMathRound: return "round";
727 case kMathCeil: return "ceil";
728 case kMathAbs: return "abs";
729 case kMathLog: return "log";
730 case kMathSin: return "sin";
731 case kMathCos: return "cos";
732 case kMathTan: return "tan";
733 case kMathASin: return "asin";
734 case kMathACos: return "acos";
735 case kMathATan: return "atan";
736 case kMathExp: return "exp";
737 case kMathSqrt: return "sqrt";
738 default: break;
739 }
740 return "(unknown operation)";
741}
742
743
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000744void HUnaryMathOperation::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000745 const char* name = OpName();
746 stream->Add("%s ", name);
747 value()->PrintNameTo(stream);
748}
749
750
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000751void HUnaryOperation::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000752 value()->PrintNameTo(stream);
753}
754
755
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000756void HHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000757 value()->PrintNameTo(stream);
758 switch (from_) {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000759 case FIRST_JS_RECEIVER_TYPE:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000760 if (to_ == LAST_TYPE) stream->Add(" spec_object");
761 break;
762 case JS_REGEXP_TYPE:
763 if (to_ == JS_REGEXP_TYPE) stream->Add(" reg_exp");
764 break;
765 case JS_ARRAY_TYPE:
766 if (to_ == JS_ARRAY_TYPE) stream->Add(" array");
767 break;
768 case JS_FUNCTION_TYPE:
769 if (to_ == JS_FUNCTION_TYPE) stream->Add(" function");
770 break;
771 default:
772 break;
773 }
774}
775
776
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000777void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000778 value()->PrintNameTo(stream);
779 stream->Add(" == ");
780 stream->Add(type_literal_->ToAsciiVector());
781}
782
783
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000784void HChange::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000785 HUnaryOperation::PrintDataTo(stream);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000786 stream->Add(" %s to %s", from_.Mnemonic(), to().Mnemonic());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000787
788 if (CanTruncateToInt32()) stream->Add(" truncating-int32");
789 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
790}
791
792
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000793HValue* HCheckInstanceType::Canonicalize() {
794 if (check_ == IS_STRING &&
795 !value()->type().IsUninitialized() &&
796 value()->type().IsString()) {
797 return NULL;
798 }
799 if (check_ == IS_SYMBOL &&
800 value()->IsConstant() &&
801 HConstant::cast(value())->handle()->IsSymbol()) {
802 return NULL;
803 }
804 return this;
805}
806
807
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000808void HCheckInstanceType::GetCheckInterval(InstanceType* first,
809 InstanceType* last) {
810 ASSERT(is_interval_check());
811 switch (check_) {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000812 case IS_SPEC_OBJECT:
813 *first = FIRST_SPEC_OBJECT_TYPE;
814 *last = LAST_SPEC_OBJECT_TYPE;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000815 return;
816 case IS_JS_ARRAY:
817 *first = *last = JS_ARRAY_TYPE;
818 return;
819 default:
820 UNREACHABLE();
821 }
822}
823
824
825void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
826 ASSERT(!is_interval_check());
827 switch (check_) {
828 case IS_STRING:
829 *mask = kIsNotStringMask;
830 *tag = kStringTag;
831 return;
832 case IS_SYMBOL:
833 *mask = kIsSymbolMask;
834 *tag = kSymbolTag;
835 return;
836 default:
837 UNREACHABLE();
838 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000839}
840
841
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000842void HCheckMap::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000843 value()->PrintNameTo(stream);
844 stream->Add(" %p", *map());
845}
846
847
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000848void HCheckFunction::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000849 value()->PrintNameTo(stream);
850 stream->Add(" %p", *target());
851}
852
853
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000854void HCallStub::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000855 stream->Add("%s ",
856 CodeStub::MajorName(major_key_, false));
857 HUnaryCall::PrintDataTo(stream);
858}
859
860
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000861void HInstanceOf::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000862 left()->PrintNameTo(stream);
863 stream->Add(" ");
864 right()->PrintNameTo(stream);
865 stream->Add(" ");
866 context()->PrintNameTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000867}
868
869
870Range* HValue::InferRange() {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000871 // Untagged integer32 cannot be -0, all other representations can.
872 Range* result = new Range();
873 result->set_can_be_minus_zero(!representation().IsInteger32());
874 return result;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000875}
876
877
878Range* HConstant::InferRange() {
879 if (has_int32_value_) {
880 Range* result = new Range(int32_value_, int32_value_);
881 result->set_can_be_minus_zero(false);
882 return result;
883 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000884 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000885}
886
887
888Range* HPhi::InferRange() {
889 if (representation().IsInteger32()) {
890 if (block()->IsLoopHeader()) {
891 Range* range = new Range(kMinInt, kMaxInt);
892 return range;
893 } else {
894 Range* range = OperandAt(0)->range()->Copy();
895 for (int i = 1; i < OperandCount(); ++i) {
896 range->Union(OperandAt(i)->range());
897 }
898 return range;
899 }
900 } else {
901 return HValue::InferRange();
902 }
903}
904
905
906Range* HAdd::InferRange() {
907 if (representation().IsInteger32()) {
908 Range* a = left()->range();
909 Range* b = right()->range();
910 Range* res = a->Copy();
911 if (!res->AddAndCheckOverflow(b)) {
912 ClearFlag(kCanOverflow);
913 }
914 bool m0 = a->CanBeMinusZero() && b->CanBeMinusZero();
915 res->set_can_be_minus_zero(m0);
916 return res;
917 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000918 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000919 }
920}
921
922
923Range* HSub::InferRange() {
924 if (representation().IsInteger32()) {
925 Range* a = left()->range();
926 Range* b = right()->range();
927 Range* res = a->Copy();
928 if (!res->SubAndCheckOverflow(b)) {
929 ClearFlag(kCanOverflow);
930 }
931 res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
932 return res;
933 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000934 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000935 }
936}
937
938
939Range* HMul::InferRange() {
940 if (representation().IsInteger32()) {
941 Range* a = left()->range();
942 Range* b = right()->range();
943 Range* res = a->Copy();
944 if (!res->MulAndCheckOverflow(b)) {
945 ClearFlag(kCanOverflow);
946 }
947 bool m0 = (a->CanBeZero() && b->CanBeNegative()) ||
948 (a->CanBeNegative() && b->CanBeZero());
949 res->set_can_be_minus_zero(m0);
950 return res;
951 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000952 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000953 }
954}
955
956
957Range* HDiv::InferRange() {
958 if (representation().IsInteger32()) {
959 Range* result = new Range();
960 if (left()->range()->CanBeMinusZero()) {
961 result->set_can_be_minus_zero(true);
962 }
963
964 if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) {
965 result->set_can_be_minus_zero(true);
966 }
967
968 if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
969 SetFlag(HValue::kCanOverflow);
970 }
971
972 if (!right()->range()->CanBeZero()) {
973 ClearFlag(HValue::kCanBeDivByZero);
974 }
975 return result;
976 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000977 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000978 }
979}
980
981
982Range* HMod::InferRange() {
983 if (representation().IsInteger32()) {
984 Range* a = left()->range();
985 Range* result = new Range();
986 if (a->CanBeMinusZero() || a->CanBeNegative()) {
987 result->set_can_be_minus_zero(true);
988 }
989 if (!right()->range()->CanBeZero()) {
990 ClearFlag(HValue::kCanBeDivByZero);
991 }
992 return result;
993 } else {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000994 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000995 }
996}
997
998
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000999void HPhi::PrintTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001000 stream->Add("[");
1001 for (int i = 0; i < OperandCount(); ++i) {
1002 HValue* value = OperandAt(i);
1003 stream->Add(" ");
1004 value->PrintNameTo(stream);
1005 stream->Add(" ");
1006 }
1007 stream->Add(" uses%d_%di_%dd_%dt]",
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001008 UseCount(),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001009 int32_non_phi_uses() + int32_indirect_uses(),
1010 double_non_phi_uses() + double_indirect_uses(),
1011 tagged_non_phi_uses() + tagged_indirect_uses());
1012}
1013
1014
1015void HPhi::AddInput(HValue* value) {
1016 inputs_.Add(NULL);
1017 SetOperandAt(OperandCount() - 1, value);
1018 // Mark phis that may have 'arguments' directly or indirectly as an operand.
1019 if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) {
1020 SetFlag(kIsArguments);
1021 }
1022}
1023
1024
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001025bool HPhi::HasRealUses() {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001026 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1027 if (!it.value()->IsPhi()) return true;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001028 }
1029 return false;
1030}
1031
1032
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001033HValue* HPhi::GetRedundantReplacement() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001034 HValue* candidate = NULL;
1035 int count = OperandCount();
1036 int position = 0;
1037 while (position < count && candidate == NULL) {
1038 HValue* current = OperandAt(position++);
1039 if (current != this) candidate = current;
1040 }
1041 while (position < count) {
1042 HValue* current = OperandAt(position++);
1043 if (current != this && current != candidate) return NULL;
1044 }
1045 ASSERT(candidate != this);
1046 return candidate;
1047}
1048
1049
1050void HPhi::DeleteFromGraph() {
1051 ASSERT(block() != NULL);
1052 block()->RemovePhi(this);
1053 ASSERT(block() == NULL);
1054}
1055
1056
1057void HPhi::InitRealUses(int phi_id) {
1058 // Initialize real uses.
1059 phi_id_ = phi_id;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001060 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1061 HValue* value = it.value();
1062 if (!value->IsPhi()) {
1063 Representation rep = value->RequiredInputRepresentation(it.index());
1064 ++non_phi_uses_[rep.kind()];
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001065 }
1066 }
1067}
1068
1069
1070void HPhi::AddNonPhiUsesFrom(HPhi* other) {
1071 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1072 indirect_uses_[i] += other->non_phi_uses_[i];
1073 }
1074}
1075
1076
1077void HPhi::AddIndirectUsesTo(int* dest) {
1078 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1079 dest[i] += indirect_uses_[i];
1080 }
1081}
1082
1083
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001084void HSimulate::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001085 stream->Add("id=%d ", ast_id());
1086 if (pop_count_ > 0) stream->Add("pop %d", pop_count_);
1087 if (values_.length() > 0) {
1088 if (pop_count_ > 0) stream->Add(" /");
1089 for (int i = 0; i < values_.length(); ++i) {
1090 if (!HasAssignedIndexAt(i)) {
1091 stream->Add(" push ");
1092 } else {
1093 stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
1094 }
1095 values_[i]->PrintNameTo(stream);
1096 }
1097 }
1098}
1099
1100
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00001101void HDeoptimize::PrintDataTo(StringStream* stream) {
1102 if (OperandCount() == 0) return;
1103 OperandAt(0)->PrintNameTo(stream);
1104 for (int i = 1; i < OperandCount(); ++i) {
1105 stream->Add(" ");
1106 OperandAt(i)->PrintNameTo(stream);
1107 }
1108}
1109
1110
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001111void HEnterInlined::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001112 SmartPointer<char> name = function()->debug_name()->ToCString();
1113 stream->Add("%s, id=%d", *name, function()->id());
1114}
1115
1116
1117HConstant::HConstant(Handle<Object> handle, Representation r)
1118 : handle_(handle),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001119 has_int32_value_(false),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001120 has_double_value_(false),
danno@chromium.org160a7b02011-04-18 15:51:38 +00001121 int32_value_(0),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001122 double_value_(0) {
1123 set_representation(r);
1124 SetFlag(kUseGVN);
1125 if (handle_->IsNumber()) {
1126 double n = handle_->Number();
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001127 double roundtrip_value = static_cast<double>(static_cast<int32_t>(n));
1128 has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001129 if (has_int32_value_) int32_value_ = static_cast<int32_t>(n);
1130 double_value_ = n;
1131 has_double_value_ = true;
1132 }
1133}
1134
1135
1136HConstant* HConstant::CopyToRepresentation(Representation r) const {
1137 if (r.IsInteger32() && !has_int32_value_) return NULL;
1138 if (r.IsDouble() && !has_double_value_) return NULL;
1139 return new HConstant(handle_, r);
1140}
1141
1142
1143HConstant* HConstant::CopyToTruncatedInt32() const {
1144 if (!has_double_value_) return NULL;
1145 int32_t truncated = NumberToInt32(*handle_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001146 return new HConstant(FACTORY->NewNumberFromInt(truncated),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001147 Representation::Integer32());
1148}
1149
1150
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001151bool HConstant::ToBoolean() const {
1152 // Converts the constant's boolean value according to
1153 // ECMAScript section 9.2 ToBoolean conversion.
1154 if (HasInteger32Value()) return Integer32Value() != 0;
1155 if (HasDoubleValue()) {
1156 double v = DoubleValue();
1157 return v != 0 && !isnan(v);
1158 }
1159 if (handle()->IsTrue()) return true;
1160 if (handle()->IsFalse()) return false;
1161 if (handle()->IsUndefined()) return false;
1162 if (handle()->IsNull()) return false;
1163 if (handle()->IsString() &&
1164 String::cast(*handle())->length() == 0) return false;
1165 return true;
1166}
1167
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001168void HConstant::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001169 handle()->ShortPrint(stream);
1170}
1171
1172
1173bool HArrayLiteral::IsCopyOnWrite() const {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001174 return constant_elements()->map() == HEAP->fixed_cow_array_map();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001175}
1176
1177
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001178void HBinaryOperation::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001179 left()->PrintNameTo(stream);
1180 stream->Add(" ");
1181 right()->PrintNameTo(stream);
1182 if (CheckFlag(kCanOverflow)) stream->Add(" !");
1183 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1184}
1185
1186
1187Range* HBitAnd::InferRange() {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001188 int32_t left_mask = (left()->range() != NULL)
1189 ? left()->range()->Mask()
1190 : 0xffffffff;
1191 int32_t right_mask = (right()->range() != NULL)
1192 ? right()->range()->Mask()
1193 : 0xffffffff;
1194 int32_t result_mask = left_mask & right_mask;
1195 return (result_mask >= 0)
1196 ? new Range(0, result_mask)
1197 : HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001198}
1199
1200
1201Range* HBitOr::InferRange() {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001202 int32_t left_mask = (left()->range() != NULL)
1203 ? left()->range()->Mask()
1204 : 0xffffffff;
1205 int32_t right_mask = (right()->range() != NULL)
1206 ? right()->range()->Mask()
1207 : 0xffffffff;
1208 int32_t result_mask = left_mask | right_mask;
1209 return (result_mask >= 0)
1210 ? new Range(0, result_mask)
1211 : HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001212}
1213
1214
1215Range* HSar::InferRange() {
1216 if (right()->IsConstant()) {
1217 HConstant* c = HConstant::cast(right());
1218 if (c->HasInteger32Value()) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001219 Range* result = (left()->range() != NULL)
1220 ? left()->range()->Copy()
1221 : new Range();
1222 result->Sar(c->Integer32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001223 return result;
1224 }
1225 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001226 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001227}
1228
1229
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001230Range* HShr::InferRange() {
1231 if (right()->IsConstant()) {
1232 HConstant* c = HConstant::cast(right());
1233 if (c->HasInteger32Value()) {
1234 int shift_count = c->Integer32Value() & 0x1f;
1235 if (left()->range()->CanBeNegative()) {
1236 // Only compute bounds if the result always fits into an int32.
1237 return (shift_count >= 1)
1238 ? new Range(0, static_cast<uint32_t>(0xffffffff) >> shift_count)
1239 : new Range();
1240 } else {
1241 // For positive inputs we can use the >> operator.
1242 Range* result = (left()->range() != NULL)
1243 ? left()->range()->Copy()
1244 : new Range();
1245 result->Sar(c->Integer32Value());
1246 return result;
1247 }
1248 }
1249 }
1250 return HValue::InferRange();
1251}
1252
1253
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001254Range* HShl::InferRange() {
1255 if (right()->IsConstant()) {
1256 HConstant* c = HConstant::cast(right());
1257 if (c->HasInteger32Value()) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001258 Range* result = (left()->range() != NULL)
1259 ? left()->range()->Copy()
1260 : new Range();
1261 result->Shl(c->Integer32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001262 return result;
1263 }
1264 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001265 return HValue::InferRange();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001266}
1267
1268
1269
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001270void HCompareGeneric::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001271 stream->Add(Token::Name(token()));
1272 stream->Add(" ");
1273 HBinaryOperation::PrintDataTo(stream);
1274}
1275
1276
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001277void HCompareIDAndBranch::PrintDataTo(StringStream* stream) {
1278 stream->Add(Token::Name(token()));
1279 stream->Add(" ");
1280 left()->PrintNameTo(stream);
1281 stream->Add(" ");
1282 right()->PrintNameTo(stream);
1283}
1284
1285
1286void HCompareIDAndBranch::SetInputRepresentation(Representation r) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001287 input_representation_ = r;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001288 if (r.IsDouble()) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001289 SetFlag(kDeoptimizeOnUndefined);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001290 } else {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001291 ASSERT(r.IsInteger32());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001292 }
1293}
1294
1295
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001296void HParameter::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001297 stream->Add("%u", index());
1298}
1299
1300
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001301void HLoadNamedField::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001302 object()->PrintNameTo(stream);
1303 stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1304}
1305
1306
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001307HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
1308 HValue* object,
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001309 ZoneMapList* types,
1310 Handle<String> name)
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001311 : types_(Min(types->length(), kMaxLoadPolymorphism)),
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001312 name_(name),
1313 need_generic_(false) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001314 SetOperandAt(0, context);
1315 SetOperandAt(1, object);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001316 set_representation(Representation::Tagged());
1317 SetFlag(kDependsOnMaps);
1318 for (int i = 0;
1319 i < types->length() && types_.length() < kMaxLoadPolymorphism;
1320 ++i) {
1321 Handle<Map> map = types->at(i);
1322 LookupResult lookup;
1323 map->LookupInDescriptors(NULL, *name, &lookup);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001324 if (lookup.IsProperty()) {
1325 switch (lookup.type()) {
1326 case FIELD: {
1327 int index = lookup.GetLocalFieldIndexFromMap(*map);
1328 if (index < 0) {
1329 SetFlag(kDependsOnInobjectFields);
1330 } else {
1331 SetFlag(kDependsOnBackingStoreFields);
1332 }
1333 types_.Add(types->at(i));
1334 break;
1335 }
1336 case CONSTANT_FUNCTION:
1337 types_.Add(types->at(i));
1338 break;
1339 default:
1340 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001341 }
1342 }
1343 }
1344
1345 if (types_.length() == types->length() && FLAG_deoptimize_uncommon_cases) {
1346 SetFlag(kUseGVN);
1347 } else {
1348 SetAllSideEffects();
1349 need_generic_ = true;
1350 }
1351}
1352
1353
1354bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
1355 HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
1356 if (types_.length() != other->types()->length()) return false;
1357 if (!name_.is_identical_to(other->name())) return false;
1358 if (need_generic_ != other->need_generic_) return false;
1359 for (int i = 0; i < types_.length(); i++) {
1360 bool found = false;
1361 for (int j = 0; j < types_.length(); j++) {
1362 if (types_.at(j).is_identical_to(other->types()->at(i))) {
1363 found = true;
1364 break;
1365 }
1366 }
1367 if (!found) return false;
1368 }
1369 return true;
1370}
1371
1372
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001373void HLoadNamedFieldPolymorphic::PrintDataTo(StringStream* stream) {
1374 object()->PrintNameTo(stream);
1375 stream->Add(" .");
1376 stream->Add(*String::cast(*name())->ToCString());
1377}
1378
1379
1380void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
1381 object()->PrintNameTo(stream);
1382 stream->Add(" .");
1383 stream->Add(*String::cast(*name())->ToCString());
1384}
1385
1386
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001387void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001388 object()->PrintNameTo(stream);
1389 stream->Add("[");
1390 key()->PrintNameTo(stream);
1391 stream->Add("]");
1392}
1393
1394
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001395bool HLoadKeyedFastElement::RequiresHoleCheck() const {
1396 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1397 HValue* use = it.value();
1398 if (!use->IsChange()) return true;
1399 }
1400 return false;
1401}
1402
1403
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001404void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
1405 elements()->PrintNameTo(stream);
1406 stream->Add("[");
1407 key()->PrintNameTo(stream);
1408 stream->Add("]");
1409}
1410
1411
1412bool HLoadKeyedFastDoubleElement::RequiresHoleCheck() const {
1413 return true;
1414}
1415
1416
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001417void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
1418 object()->PrintNameTo(stream);
1419 stream->Add("[");
1420 key()->PrintNameTo(stream);
1421 stream->Add("]");
1422}
1423
1424
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001425void HLoadKeyedSpecializedArrayElement::PrintDataTo(
1426 StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001427 external_pointer()->PrintNameTo(stream);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001428 stream->Add(".");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001429 switch (elements_kind()) {
1430 case JSObject::EXTERNAL_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001431 stream->Add("byte");
1432 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001433 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001434 stream->Add("u_byte");
1435 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001436 case JSObject::EXTERNAL_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001437 stream->Add("short");
1438 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001439 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001440 stream->Add("u_short");
1441 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001442 case JSObject::EXTERNAL_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001443 stream->Add("int");
1444 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001445 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001446 stream->Add("u_int");
1447 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001448 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001449 stream->Add("float");
1450 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001451 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001452 stream->Add("double");
1453 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001454 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001455 stream->Add("pixel");
1456 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001457 case JSObject::FAST_ELEMENTS:
1458 case JSObject::FAST_DOUBLE_ELEMENTS:
1459 case JSObject::DICTIONARY_ELEMENTS:
whesse@chromium.org7b260152011-06-20 15:33:18 +00001460 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001461 UNREACHABLE();
1462 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001463 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001464 stream->Add("[");
1465 key()->PrintNameTo(stream);
1466 stream->Add("]");
1467}
1468
1469
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001470void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001471 object()->PrintNameTo(stream);
1472 stream->Add(".");
1473 ASSERT(name()->IsString());
1474 stream->Add(*String::cast(*name())->ToCString());
1475 stream->Add(" = ");
1476 value()->PrintNameTo(stream);
1477}
1478
1479
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001480void HStoreNamedField::PrintDataTo(StringStream* stream) {
1481 object()->PrintNameTo(stream);
1482 stream->Add(".");
1483 ASSERT(name()->IsString());
1484 stream->Add(*String::cast(*name())->ToCString());
1485 stream->Add(" = ");
1486 value()->PrintNameTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001487 if (!transition().is_null()) {
1488 stream->Add(" (transition map %p)", *transition());
1489 }
1490}
1491
1492
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001493void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001494 object()->PrintNameTo(stream);
1495 stream->Add("[");
1496 key()->PrintNameTo(stream);
1497 stream->Add("] = ");
1498 value()->PrintNameTo(stream);
1499}
1500
1501
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001502void HStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
1503 elements()->PrintNameTo(stream);
1504 stream->Add("[");
1505 key()->PrintNameTo(stream);
1506 stream->Add("] = ");
1507 value()->PrintNameTo(stream);
1508}
1509
1510
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001511void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
1512 object()->PrintNameTo(stream);
1513 stream->Add("[");
1514 key()->PrintNameTo(stream);
1515 stream->Add("] = ");
1516 value()->PrintNameTo(stream);
1517}
1518
1519
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001520void HStoreKeyedSpecializedArrayElement::PrintDataTo(
1521 StringStream* stream) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001522 external_pointer()->PrintNameTo(stream);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001523 stream->Add(".");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001524 switch (elements_kind()) {
1525 case JSObject::EXTERNAL_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001526 stream->Add("byte");
1527 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001528 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001529 stream->Add("u_byte");
1530 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001531 case JSObject::EXTERNAL_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001532 stream->Add("short");
1533 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001534 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001535 stream->Add("u_short");
1536 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001537 case JSObject::EXTERNAL_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001538 stream->Add("int");
1539 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001540 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001541 stream->Add("u_int");
1542 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001543 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001544 stream->Add("float");
1545 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001546 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001547 stream->Add("double");
1548 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001549 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001550 stream->Add("pixel");
1551 break;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001552 case JSObject::FAST_ELEMENTS:
1553 case JSObject::FAST_DOUBLE_ELEMENTS:
1554 case JSObject::DICTIONARY_ELEMENTS:
whesse@chromium.org7b260152011-06-20 15:33:18 +00001555 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001556 UNREACHABLE();
1557 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001558 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001559 stream->Add("[");
1560 key()->PrintNameTo(stream);
1561 stream->Add("] = ");
1562 value()->PrintNameTo(stream);
1563}
1564
1565
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001566void HLoadGlobalCell::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001567 stream->Add("[%p]", *cell());
1568 if (check_hole_value()) stream->Add(" (deleteable/read-only)");
1569}
1570
1571
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001572void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) {
1573 stream->Add("%o ", *name());
1574}
1575
1576
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001577void HStoreGlobalCell::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001578 stream->Add("[%p] = ", *cell());
1579 value()->PrintNameTo(stream);
1580}
1581
1582
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001583void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
1584 stream->Add("%o = ", *name());
1585 value()->PrintNameTo(stream);
1586}
1587
1588
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001589void HLoadContextSlot::PrintDataTo(StringStream* stream) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001590 value()->PrintNameTo(stream);
1591 stream->Add("[%d]", slot_index());
1592}
1593
1594
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001595void HStoreContextSlot::PrintDataTo(StringStream* stream) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001596 context()->PrintNameTo(stream);
1597 stream->Add("[%d] = ", slot_index());
1598 value()->PrintNameTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001599}
1600
1601
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001602// Implementation of type inference and type conversions. Calculates
1603// the inferred type of this instruction based on the input operands.
1604
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001605HType HValue::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001606 return type_;
1607}
1608
1609
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001610HType HCheckMap::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001611 return value()->type();
1612}
1613
1614
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001615HType HCheckFunction::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001616 return value()->type();
1617}
1618
1619
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001620HType HCheckNonSmi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001621 // TODO(kasperl): Is there any way to signal that this isn't a smi?
1622 return HType::Tagged();
1623}
1624
1625
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001626HType HCheckSmi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001627 return HType::Smi();
1628}
1629
1630
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001631HType HPhi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001632 HType result = HType::Uninitialized();
1633 for (int i = 0; i < OperandCount(); ++i) {
1634 HType current = OperandAt(i)->type();
1635 result = result.Combine(current);
1636 }
1637 return result;
1638}
1639
1640
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001641HType HConstant::CalculateInferredType() {
danno@chromium.org160a7b02011-04-18 15:51:38 +00001642 return HType::TypeFromValue(handle_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001643}
1644
1645
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001646HType HCompareGeneric::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001647 return HType::Boolean();
1648}
1649
1650
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001651HType HInstanceOf::CalculateInferredType() {
1652 return HType::Boolean();
1653}
1654
1655
1656HType HDeleteProperty::CalculateInferredType() {
1657 return HType::Boolean();
1658}
1659
1660
1661HType HInstanceOfKnownGlobal::CalculateInferredType() {
1662 return HType::Boolean();
1663}
1664
1665
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001666HType HBitwiseBinaryOperation::CalculateInferredType() {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001667 return HType::TaggedNumber();
1668}
1669
1670
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001671HType HArithmeticBinaryOperation::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001672 return HType::TaggedNumber();
1673}
1674
1675
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001676HType HAdd::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001677 return HType::Tagged();
1678}
1679
1680
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001681HType HBitAnd::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001682 return HType::TaggedNumber();
1683}
1684
1685
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001686HType HBitXor::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001687 return HType::TaggedNumber();
1688}
1689
1690
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001691HType HBitOr::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001692 return HType::TaggedNumber();
1693}
1694
1695
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001696HType HBitNot::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001697 return HType::TaggedNumber();
1698}
1699
1700
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001701HType HUnaryMathOperation::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001702 return HType::TaggedNumber();
1703}
1704
1705
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001706HType HShl::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001707 return HType::TaggedNumber();
1708}
1709
1710
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001711HType HShr::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001712 return HType::TaggedNumber();
1713}
1714
1715
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001716HType HSar::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001717 return HType::TaggedNumber();
1718}
1719
1720
1721HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero(
1722 BitVector* visited) {
1723 visited->Add(id());
1724 if (representation().IsInteger32() &&
1725 !value()->representation().IsInteger32()) {
1726 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
1727 SetFlag(kBailoutOnMinusZero);
1728 }
1729 }
1730 if (RequiredInputRepresentation(0).IsInteger32() &&
1731 representation().IsInteger32()) {
1732 return value();
1733 }
1734 return NULL;
1735}
1736
1737
1738
1739HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1740 visited->Add(id());
1741 if (from().IsInteger32()) return NULL;
1742 if (CanTruncateToInt32()) return NULL;
1743 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
1744 SetFlag(kBailoutOnMinusZero);
1745 }
1746 ASSERT(!from().IsInteger32() || !to().IsInteger32());
1747 return NULL;
1748}
1749
1750
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001751HValue* HForceRepresentation::EnsureAndPropagateNotMinusZero(
1752 BitVector* visited) {
1753 visited->Add(id());
1754 return value();
1755}
1756
1757
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001758HValue* HMod::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1759 visited->Add(id());
1760 if (range() == NULL || range()->CanBeMinusZero()) {
1761 SetFlag(kBailoutOnMinusZero);
1762 return left();
1763 }
1764 return NULL;
1765}
1766
1767
1768HValue* HDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1769 visited->Add(id());
1770 if (range() == NULL || range()->CanBeMinusZero()) {
1771 SetFlag(kBailoutOnMinusZero);
1772 }
1773 return NULL;
1774}
1775
1776
1777HValue* HMul::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1778 visited->Add(id());
1779 if (range() == NULL || range()->CanBeMinusZero()) {
1780 SetFlag(kBailoutOnMinusZero);
1781 }
1782 return NULL;
1783}
1784
1785
1786HValue* HSub::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 add operation cannot be either.
1790 if (range() == NULL || range()->CanBeMinusZero()) {
1791 return left();
1792 }
1793 return NULL;
1794}
1795
1796
1797HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1798 visited->Add(id());
1799 // Propagate to the left argument. If the left argument cannot be -0, then
1800 // the result of the sub operation cannot be either.
1801 if (range() == NULL || range()->CanBeMinusZero()) {
1802 return left();
1803 }
1804 return NULL;
1805}
1806
1807
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001808void HIn::PrintDataTo(StringStream* stream) {
1809 key()->PrintNameTo(stream);
1810 stream->Add(" ");
1811 object()->PrintNameTo(stream);
1812}
1813
1814
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001815// Node-specific verification code is only included in debug mode.
1816#ifdef DEBUG
1817
ager@chromium.org378b34e2011-01-28 08:04:38 +00001818void HPhi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001819 ASSERT(OperandCount() == block()->predecessors()->length());
1820 for (int i = 0; i < OperandCount(); ++i) {
1821 HValue* value = OperandAt(i);
1822 HBasicBlock* defining_block = value->block();
1823 HBasicBlock* predecessor_block = block()->predecessors()->at(i);
1824 ASSERT(defining_block == predecessor_block ||
1825 defining_block->Dominates(predecessor_block));
1826 }
1827}
1828
1829
ager@chromium.org378b34e2011-01-28 08:04:38 +00001830void HSimulate::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001831 HInstruction::Verify();
1832 ASSERT(HasAstId());
1833}
1834
1835
ager@chromium.org378b34e2011-01-28 08:04:38 +00001836void HCheckSmi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001837 HInstruction::Verify();
1838 ASSERT(HasNoUses());
1839}
1840
1841
ager@chromium.org378b34e2011-01-28 08:04:38 +00001842void HCheckNonSmi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001843 HInstruction::Verify();
1844 ASSERT(HasNoUses());
1845}
1846
1847
ager@chromium.org378b34e2011-01-28 08:04:38 +00001848void HCheckFunction::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001849 HInstruction::Verify();
1850 ASSERT(HasNoUses());
1851}
1852
1853
ager@chromium.org378b34e2011-01-28 08:04:38 +00001854void HCheckPrototypeMaps::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001855 HInstruction::Verify();
1856 ASSERT(HasNoUses());
1857}
1858
1859#endif
1860
1861} } // namespace v8::internal