OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 | 992 |
993 | 993 |
994 HValue* HCheckInstanceType::Canonicalize() { | 994 HValue* HCheckInstanceType::Canonicalize() { |
995 if (check_ == IS_STRING && | 995 if (check_ == IS_STRING && |
996 !value()->type().IsUninitialized() && | 996 !value()->type().IsUninitialized() && |
997 value()->type().IsString()) { | 997 value()->type().IsString()) { |
998 return NULL; | 998 return NULL; |
999 } | 999 } |
1000 if (check_ == IS_SYMBOL && | 1000 if (check_ == IS_SYMBOL && |
1001 value()->IsConstant() && | 1001 value()->IsConstant() && |
1002 HConstant::cast(value())->handle()->IsSymbol()) { | 1002 HConstant::cast(value())->IsSymbol()) { |
1003 return NULL; | 1003 return NULL; |
1004 } | 1004 } |
1005 return this; | 1005 return this; |
1006 } | 1006 } |
1007 | 1007 |
1008 | 1008 |
1009 void HCheckInstanceType::GetCheckInterval(InstanceType* first, | 1009 void HCheckInstanceType::GetCheckInterval(InstanceType* first, |
1010 InstanceType* last) { | 1010 InstanceType* last) { |
1011 ASSERT(is_interval_check()); | 1011 ASSERT(is_interval_check()); |
1012 switch (check_) { | 1012 switch (check_) { |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1377 void HEnterInlined::PrintDataTo(StringStream* stream) { | 1377 void HEnterInlined::PrintDataTo(StringStream* stream) { |
1378 SmartArrayPointer<char> name = function()->debug_name()->ToCString(); | 1378 SmartArrayPointer<char> name = function()->debug_name()->ToCString(); |
1379 stream->Add("%s, id=%d", *name, function()->id()); | 1379 stream->Add("%s, id=%d", *name, function()->id()); |
1380 } | 1380 } |
1381 | 1381 |
1382 | 1382 |
1383 HConstant::HConstant(Handle<Object> handle, Representation r) | 1383 HConstant::HConstant(Handle<Object> handle, Representation r) |
1384 : handle_(handle), | 1384 : handle_(handle), |
1385 has_int32_value_(false), | 1385 has_int32_value_(false), |
1386 has_double_value_(false), | 1386 has_double_value_(false), |
1387 int32_value_(0), | 1387 handle_was_smi_(handle->IsSmi()), |
1388 double_value_(0) { | 1388 is_string_(false), |
| 1389 is_symbol_(false), |
| 1390 is_boolean_(false) { |
1389 set_representation(r); | 1391 set_representation(r); |
1390 SetFlag(kUseGVN); | 1392 SetFlag(kUseGVN); |
1391 if (handle_->IsNumber()) { | 1393 |
| 1394 // We try to use the fact that we've already checked if the handle |
| 1395 // is a Smi. |
| 1396 if (handle_was_smi_) { |
| 1397 has_int32_value_ = true; |
| 1398 has_double_value_ = true; |
| 1399 int32_value_ = Smi::cast(*handle)->value(); |
| 1400 double_value_ = FastI2D(int32_value_); |
| 1401 } else if (handle_->IsHeapNumber()) { |
1392 double n = handle_->Number(); | 1402 double n = handle_->Number(); |
1393 double roundtrip_value = static_cast<double>(static_cast<int32_t>(n)); | 1403 double roundtrip_value = static_cast<double>(static_cast<int32_t>(n)); |
1394 has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n); | 1404 has_int32_value_ = BitCast<int64_t>(roundtrip_value) == |
1395 if (has_int32_value_) int32_value_ = static_cast<int32_t>(n); | 1405 BitCast<int64_t>(n); |
| 1406 |
| 1407 int32_value_ = DoubleToInt32(n); |
1396 double_value_ = n; | 1408 double_value_ = n; |
1397 has_double_value_ = true; | 1409 has_double_value_ = true; |
| 1410 } else { |
| 1411 is_string_ = handle->IsString(); |
| 1412 is_symbol_ = !is_string_ && handle->IsSymbol(); |
| 1413 is_boolean_ = !is_symbol_ && !is_string_ && handle->IsBoolean(); |
| 1414 } |
| 1415 } |
| 1416 |
| 1417 |
| 1418 HConstant::HConstant(int32_t integer_value, Representation r, |
| 1419 Handle<Object> handle) |
| 1420 : handle_(handle), |
| 1421 has_int32_value_(true), |
| 1422 has_double_value_(true), |
| 1423 is_string_(false), |
| 1424 is_symbol_(false), |
| 1425 is_boolean_(false) { |
| 1426 set_representation(r); |
| 1427 SetFlag(kUseGVN); |
| 1428 int32_value_ = integer_value; |
| 1429 double_value_ = FastI2D(integer_value); |
| 1430 if (handle.is_null()) { |
| 1431 // If we can safely represent this integer in 31 bits and we don't |
| 1432 // have a Handle to the HeapObject, we pretend it originated from |
| 1433 // a Smi. This is okay because when we _do_ create a HeapObject |
| 1434 // for this HConstant, it will be a Smi. |
| 1435 handle_was_smi_ = Smi::IsValid(static_cast<intptr_t>(integer_value)); |
| 1436 } else { |
| 1437 handle_was_smi_ = handle->IsSmi(); |
| 1438 } |
| 1439 } |
| 1440 |
| 1441 |
| 1442 HConstant::HConstant(double double_value, Representation r, |
| 1443 Handle<Object> handle) |
| 1444 : handle_(handle), |
| 1445 has_int32_value_(false), |
| 1446 has_double_value_(true), |
| 1447 handle_was_smi_(false), |
| 1448 is_string_(false), |
| 1449 is_symbol_(false), |
| 1450 is_boolean_(false), |
| 1451 int32_value_(DoubleToInt32(double_value)), |
| 1452 double_value_(double_value) { |
| 1453 set_representation(r); |
| 1454 SetFlag(kUseGVN); |
| 1455 double roundtrip_value = static_cast<double>( |
| 1456 static_cast<int32_t>(double_value)); |
| 1457 has_int32_value_ = BitCast<int64_t>(roundtrip_value) == |
| 1458 BitCast<int64_t>(double_value); |
| 1459 if (handle.is_null()) { |
| 1460 handle_was_smi_ = has_int32_value_ && Smi::IsValid(static_cast<intptr_t>( |
| 1461 int32_value_)); |
| 1462 } else { |
| 1463 handle_was_smi_ = handle->IsSmi(); |
| 1464 } |
| 1465 } |
| 1466 |
| 1467 |
| 1468 void HConstant::EnsureHasHandle(Factory* factory) { |
| 1469 if (handle_.is_null()) { |
| 1470 ASSERT(has_int32_value_ || has_double_value_); |
| 1471 if (has_int32_value_) { |
| 1472 handle_ = factory->NewNumberFromInt(int32_value_, TENURED); |
| 1473 ASSERT(handle_->IsSmi() || !handle_was_smi_); |
| 1474 } else { |
| 1475 handle_ = factory->NewNumber(double_value_, TENURED); |
| 1476 } |
1398 } | 1477 } |
1399 } | 1478 } |
1400 | 1479 |
1401 | 1480 |
1402 HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const { | 1481 HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const { |
1403 if (r.IsInteger32() && !has_int32_value_) return NULL; | 1482 if (has_int32_value_) { |
1404 if (r.IsDouble() && !has_double_value_) return NULL; | 1483 return new(zone) HConstant(int32_value_, r, handle_); |
1405 return new(zone) HConstant(handle_, r); | 1484 } else if (has_double_value_) { |
| 1485 // A double can be safely converted only to a HeapNumber. If it |
| 1486 // was possible to store this double as a integer, we'd have done |
| 1487 // that and has_int32_value_ would be true. |
| 1488 if (r.IsInteger32()) { |
| 1489 return NULL; |
| 1490 } else { |
| 1491 return new(zone) HConstant(double_value_, r, handle_); |
| 1492 } |
| 1493 } else { |
| 1494 // A generic tagged value cannot be safely converted to any other |
| 1495 // representation. |
| 1496 if (r.IsTagged()) { |
| 1497 return new(zone) HConstant(handle_, r); |
| 1498 } else { |
| 1499 return NULL; |
| 1500 } |
| 1501 } |
1406 } | 1502 } |
1407 | 1503 |
1408 | 1504 |
1409 HConstant* HConstant::CopyToTruncatedInt32(Zone* zone) const { | 1505 HConstant* HConstant::CopyToTruncatedInt32(Zone* zone) const { |
1410 if (!has_double_value_) return NULL; | 1506 if (has_int32_value_) { |
1411 int32_t truncated = NumberToInt32(*handle_); | 1507 return new(zone) HConstant(int32_value_, Representation::Integer32(), |
1412 return new(zone) HConstant(FACTORY->NewNumberFromInt(truncated), | 1508 handle_); |
1413 Representation::Integer32()); | 1509 } else if (has_double_value_) { |
| 1510 return new(zone) HConstant(DoubleToInt32(double_value_), |
| 1511 Representation::Integer32(), |
| 1512 Handle<Object>::null()); |
| 1513 } else { |
| 1514 return NULL; |
| 1515 } |
1414 } | 1516 } |
1415 | 1517 |
1416 | 1518 |
1417 bool HConstant::ToBoolean() const { | 1519 bool HConstant::ToBoolean() const { |
1418 // Converts the constant's boolean value according to | 1520 // Converts the constant's boolean value according to |
1419 // ECMAScript section 9.2 ToBoolean conversion. | 1521 // ECMAScript section 9.2 ToBoolean conversion. |
1420 if (HasInteger32Value()) return Integer32Value() != 0; | 1522 if (HasInteger32Value()) return Integer32Value() != 0; |
1421 if (HasDoubleValue()) { | 1523 if (HasDoubleValue()) { |
1422 double v = DoubleValue(); | 1524 double v = DoubleValue(); |
1423 return v != 0 && !isnan(v); | 1525 return v != 0 && !isnan(v); |
1424 } | 1526 } |
1425 if (handle()->IsTrue()) return true; | 1527 if (handle()->IsTrue()) return true; |
1426 if (handle()->IsFalse()) return false; | 1528 if (handle()->IsFalse()) return false; |
1427 if (handle()->IsUndefined()) return false; | 1529 if (handle()->IsUndefined()) return false; |
1428 if (handle()->IsNull()) return false; | 1530 if (handle()->IsNull()) return false; |
1429 if (handle()->IsString() && | 1531 if (handle()->IsString() && |
1430 String::cast(*handle())->length() == 0) return false; | 1532 String::cast(*handle())->length() == 0) return false; |
1431 return true; | 1533 return true; |
1432 } | 1534 } |
1433 | 1535 |
1434 void HConstant::PrintDataTo(StringStream* stream) { | 1536 void HConstant::PrintDataTo(StringStream* stream) { |
1435 handle()->ShortPrint(stream); | 1537 if (has_int32_value_) { |
| 1538 stream->Add("%d ", int32_value_); |
| 1539 } else if (has_double_value_) { |
| 1540 stream->Add("%lf ", double_value_); |
| 1541 } else { |
| 1542 handle()->ShortPrint(stream); |
| 1543 } |
1436 } | 1544 } |
1437 | 1545 |
1438 | 1546 |
1439 bool HArrayLiteral::IsCopyOnWrite() const { | 1547 bool HArrayLiteral::IsCopyOnWrite() const { |
1440 if (!boilerplate_object_->IsJSObject()) return false; | 1548 if (!boilerplate_object_->IsJSObject()) return false; |
1441 return Handle<JSObject>::cast(boilerplate_object_)->elements()->map() == | 1549 return Handle<JSObject>::cast(boilerplate_object_)->elements()->map() == |
1442 HEAP->fixed_cow_array_map(); | 1550 HEAP->fixed_cow_array_map(); |
1443 } | 1551 } |
1444 | 1552 |
1445 | 1553 |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2070 HType result = HType::Uninitialized(); | 2178 HType result = HType::Uninitialized(); |
2071 for (int i = 0; i < OperandCount(); ++i) { | 2179 for (int i = 0; i < OperandCount(); ++i) { |
2072 HType current = OperandAt(i)->type(); | 2180 HType current = OperandAt(i)->type(); |
2073 result = result.Combine(current); | 2181 result = result.Combine(current); |
2074 } | 2182 } |
2075 return result; | 2183 return result; |
2076 } | 2184 } |
2077 | 2185 |
2078 | 2186 |
2079 HType HConstant::CalculateInferredType() { | 2187 HType HConstant::CalculateInferredType() { |
2080 return HType::TypeFromValue(handle_); | 2188 if (handle_was_smi_) return HType::Smi(); |
| 2189 if (has_int32_value_ || has_double_value_) return HType::HeapNumber(); |
| 2190 return HType::TypeFromValue(Handle<Object>(handle_)); |
2081 } | 2191 } |
2082 | 2192 |
2083 | 2193 |
2084 HType HCompareGeneric::CalculateInferredType() { | 2194 HType HCompareGeneric::CalculateInferredType() { |
2085 return HType::Boolean(); | 2195 return HType::Boolean(); |
2086 } | 2196 } |
2087 | 2197 |
2088 | 2198 |
2089 HType HInstanceOf::CalculateInferredType() { | 2199 HType HInstanceOf::CalculateInferredType() { |
2090 return HType::Boolean(); | 2200 return HType::Boolean(); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2266 // If value was loaded from unboxed double backing store or | 2376 // If value was loaded from unboxed double backing store or |
2267 // converted from an integer then we don't have to canonicalize it. | 2377 // converted from an integer then we don't have to canonicalize it. |
2268 if (value()->IsLoadKeyedFastDoubleElement() || | 2378 if (value()->IsLoadKeyedFastDoubleElement() || |
2269 (value()->IsChange() && HChange::cast(value())->from().IsInteger32())) { | 2379 (value()->IsChange() && HChange::cast(value())->from().IsInteger32())) { |
2270 return false; | 2380 return false; |
2271 } | 2381 } |
2272 return true; | 2382 return true; |
2273 } | 2383 } |
2274 | 2384 |
2275 | 2385 |
2276 #define H_CONSTANT_INT32(val) \ | 2386 #define H_CONSTANT_INT32(val) \ |
2277 new(zone) HConstant(FACTORY->NewNumberFromInt(val, TENURED), \ | 2387 new(zone) HConstant(static_cast<int32_t>(val), \ |
2278 Representation::Integer32()) | 2388 Representation::Integer32(), \ |
| 2389 Handle<Object>::null()) |
| 2390 |
2279 #define H_CONSTANT_DOUBLE(val) \ | 2391 #define H_CONSTANT_DOUBLE(val) \ |
2280 new(zone) HConstant(FACTORY->NewNumber(val, TENURED), \ | 2392 new(zone) HConstant(val, Representation::Double(), Handle<Object>::null()) |
2281 Representation::Double()) | |
2282 | 2393 |
2283 #define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op) \ | 2394 #define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op) \ |
2284 HInstruction* HInstr::New##HInstr(Zone* zone, \ | 2395 HInstruction* HInstr::New##HInstr(Zone* zone, \ |
2285 HValue* context, \ | 2396 HValue* context, \ |
2286 HValue* left, \ | 2397 HValue* left, \ |
2287 HValue* right) { \ | 2398 HValue* right) { \ |
2288 if (left->IsConstant() && right->IsConstant()) { \ | 2399 if (left->IsConstant() && right->IsConstant()) { \ |
2289 HConstant* c_left = HConstant::cast(left); \ | 2400 HConstant* c_left = HConstant::cast(left); \ |
2290 HConstant* c_right = HConstant::cast(right); \ | 2401 HConstant* c_right = HConstant::cast(right); \ |
2291 if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \ | 2402 if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \ |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2528 | 2639 |
2529 | 2640 |
2530 void HCheckPrototypeMaps::Verify() { | 2641 void HCheckPrototypeMaps::Verify() { |
2531 HInstruction::Verify(); | 2642 HInstruction::Verify(); |
2532 ASSERT(HasNoUses()); | 2643 ASSERT(HasNoUses()); |
2533 } | 2644 } |
2534 | 2645 |
2535 #endif | 2646 #endif |
2536 | 2647 |
2537 } } // namespace v8::internal | 2648 } } // namespace v8::internal |
OLD | NEW |