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 2433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2444 return Representation::None(); | 2444 return Representation::None(); |
2445 } | 2445 } |
2446 | 2446 |
2447 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject) | 2447 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject) |
2448 }; | 2448 }; |
2449 | 2449 |
2450 | 2450 |
2451 class HConstant: public HTemplateInstruction<0> { | 2451 class HConstant: public HTemplateInstruction<0> { |
2452 public: | 2452 public: |
2453 HConstant(Handle<Object> handle, Representation r); | 2453 HConstant(Handle<Object> handle, Representation r); |
2454 HConstant(int32_t integer_value, Representation r, Handle<Object> handle); | |
Michael Starzinger
2012/07/09 09:57:09
I think we can get by with just two constructors.
sanjoy
2012/07/09 13:47:37
We need the double-only constructor when folding d
Michael Starzinger
2012/07/09 15:36:22
Yes, but isn't that only called during building of
| |
2455 HConstant(double double_value, Representation r, Handle<Object> handle); | |
2454 | 2456 |
2455 Handle<Object> handle() const { return handle_; } | 2457 Handle<Object> handle() const { |
2458 ASSERT(!handle_.is_null()); | |
Michael Starzinger
2012/07/09 09:57:09
This change introduces a large amount of complexit
sanjoy
2012/07/09 13:47:37
Fixed. handle() now lazily allocates a Handle.
| |
2459 return handle_; | |
2460 } | |
2456 | 2461 |
2457 bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); } | 2462 bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); } |
2458 | 2463 |
2459 bool ImmortalImmovable() const { | 2464 bool ImmortalImmovable() const { |
2465 if (has_int32_value_) { | |
2466 return false; | |
2467 } | |
2468 if (has_double_value_) { | |
2469 if (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) || | |
2470 isnan(double_value_)) { | |
2471 return true; | |
2472 } | |
2473 return false; | |
2474 } | |
2460 Heap* heap = HEAP; | 2475 Heap* heap = HEAP; |
2476 // We should have handled minus_zero_value and nan_value in the | |
2477 // has_double_value_ clause above. | |
2478 ASSERT(*handle_ != heap->minus_zero_value()); | |
2479 ASSERT(*handle_ != heap->nan_value()); | |
2461 if (*handle_ == heap->undefined_value()) return true; | 2480 if (*handle_ == heap->undefined_value()) return true; |
2462 if (*handle_ == heap->null_value()) return true; | 2481 if (*handle_ == heap->null_value()) return true; |
2463 if (*handle_ == heap->true_value()) return true; | 2482 if (*handle_ == heap->true_value()) return true; |
2464 if (*handle_ == heap->false_value()) return true; | 2483 if (*handle_ == heap->false_value()) return true; |
2465 if (*handle_ == heap->the_hole_value()) return true; | 2484 if (*handle_ == heap->the_hole_value()) return true; |
2466 if (*handle_ == heap->minus_zero_value()) return true; | |
2467 if (*handle_ == heap->nan_value()) return true; | |
2468 if (*handle_ == heap->empty_string()) return true; | 2485 if (*handle_ == heap->empty_string()) return true; |
2469 return false; | 2486 return false; |
2470 } | 2487 } |
2471 | 2488 |
2472 virtual Representation RequiredInputRepresentation(int index) { | 2489 virtual Representation RequiredInputRepresentation(int index) { |
2473 return Representation::None(); | 2490 return Representation::None(); |
2474 } | 2491 } |
2475 | 2492 |
2493 void EnsureHasHandle(Factory* factory); | |
2494 bool IsTagged() { | |
2495 ASSERT(has_int32_value_ || has_double_value_ || !handle_.is_null()); | |
2496 return !(has_int32_value_ || has_double_value_); | |
2497 } | |
2498 | |
2476 virtual bool IsConvertibleToInteger() const { | 2499 virtual bool IsConvertibleToInteger() const { |
2477 if (handle_->IsSmi()) return true; | 2500 return has_int32_value_; |
2478 if (handle_->IsHeapNumber() && | |
2479 (HeapNumber::cast(*handle_)->value() == | |
2480 static_cast<double>(NumberToInt32(*handle_)))) return true; | |
2481 return false; | |
2482 } | 2501 } |
2483 | 2502 |
2484 virtual bool EmitAtUses() { return !representation().IsDouble(); } | 2503 virtual bool EmitAtUses() { return !representation().IsDouble(); } |
2485 virtual HValue* Canonicalize(); | 2504 virtual HValue* Canonicalize(); |
2486 virtual void PrintDataTo(StringStream* stream); | 2505 virtual void PrintDataTo(StringStream* stream); |
2487 virtual HType CalculateInferredType(); | 2506 virtual HType CalculateInferredType(); |
2488 bool IsInteger() const { return handle_->IsSmi(); } | 2507 bool IsInteger() const { return handle_was_smi_; } |
2489 HConstant* CopyToRepresentation(Representation r, Zone* zone) const; | 2508 HConstant* CopyToRepresentation(Representation r, Zone* zone) const; |
2490 HConstant* CopyToTruncatedInt32(Zone* zone) const; | 2509 HConstant* CopyToTruncatedInt32(Zone* zone) const; |
2491 bool HasInteger32Value() const { return has_int32_value_; } | 2510 bool HasInteger32Value() const { return has_int32_value_; } |
2492 int32_t Integer32Value() const { | 2511 int32_t Integer32Value() const { |
2493 ASSERT(HasInteger32Value()); | 2512 ASSERT(HasInteger32Value()); |
2494 return int32_value_; | 2513 return int32_value_; |
2495 } | 2514 } |
2496 bool HasDoubleValue() const { return has_double_value_; } | 2515 bool HasDoubleValue() const { return has_double_value_; } |
2497 double DoubleValue() const { | 2516 double DoubleValue() const { |
2498 ASSERT(HasDoubleValue()); | 2517 ASSERT(HasDoubleValue()); |
2499 return double_value_; | 2518 return double_value_; |
2500 } | 2519 } |
2501 bool HasNumberValue() const { return has_int32_value_ || has_double_value_; } | 2520 bool HasNumberValue() const { return has_double_value_; } |
2502 int32_t NumberValueAsInteger32() const { | 2521 int32_t NumberValueAsInteger32() const { |
2503 ASSERT(HasNumberValue()); | 2522 ASSERT(HasNumberValue()); |
2504 if (has_int32_value_) return int32_value_; | 2523 return int32_value_; |
2505 return DoubleToInt32(double_value_); | |
2506 } | 2524 } |
2507 bool HasStringValue() const { return handle_->IsString(); } | 2525 bool IsString() const { return is_string_; } |
2526 bool IsBoolean() const { return is_boolean_; } | |
2527 bool IsSymbol() { return is_symbol_; } | |
2508 | 2528 |
2509 bool ToBoolean() const; | 2529 bool ToBoolean() const; |
2510 | 2530 |
2511 virtual intptr_t Hashcode() { | 2531 virtual intptr_t Hashcode() { |
2512 ASSERT(!HEAP->allow_allocation(false)); | 2532 ASSERT(!HEAP->allow_allocation(false)); |
2513 intptr_t hash = reinterpret_cast<intptr_t>(*handle()); | 2533 intptr_t hash; |
2514 // Prevent smis from having fewer hash values when truncated to | 2534 |
2515 // the least significant bits. | 2535 if (has_int32_value_) { |
2516 const int kShiftSize = kSmiShiftSize + kSmiTagSize; | 2536 hash = static_cast<intptr_t>(int32_value_); |
2517 STATIC_ASSERT(kShiftSize != 0); | 2537 // Prevent smis from having fewer hash values when truncated to |
2518 return hash ^ (hash >> kShiftSize); | 2538 // the least significant bits. |
2539 const int kShiftSize = kSmiShiftSize + kSmiTagSize; | |
2540 STATIC_ASSERT(kShiftSize != 0); | |
2541 hash = hash ^ (hash >> kShiftSize); | |
2542 } else if (has_double_value_) { | |
2543 hash = static_cast<intptr_t>(BitCast<int64_t>(double_value_)); | |
2544 } else { | |
2545 ASSERT(!handle_.is_null()); | |
2546 hash = reinterpret_cast<intptr_t>(*handle_); | |
2547 } | |
2548 | |
2549 return hash; | |
2519 } | 2550 } |
2520 | 2551 |
2521 #ifdef DEBUG | 2552 #ifdef DEBUG |
2522 virtual void Verify() { } | 2553 virtual void Verify() { } |
2523 #endif | 2554 #endif |
2524 | 2555 |
2525 DECLARE_CONCRETE_INSTRUCTION(Constant) | 2556 DECLARE_CONCRETE_INSTRUCTION(Constant) |
2526 | 2557 |
2527 protected: | 2558 protected: |
2528 virtual Range* InferRange(Zone* zone); | 2559 virtual Range* InferRange(Zone* zone); |
2529 | 2560 |
2530 virtual bool DataEquals(HValue* other) { | 2561 virtual bool DataEquals(HValue* other) { |
2531 HConstant* other_constant = HConstant::cast(other); | 2562 HConstant* other_constant = HConstant::cast(other); |
2532 return handle().is_identical_to(other_constant->handle()); | 2563 if (has_int32_value_) { |
2564 return other_constant->has_int32_value_ && | |
2565 int32_value_ == other_constant->int32_value_; | |
2566 } else if (has_double_value_) { | |
2567 return other_constant->has_double_value_ && | |
2568 BitCast<int64_t>(double_value_) == | |
2569 BitCast<int64_t>(other_constant->double_value_); | |
2570 } else { | |
2571 ASSERT(!handle_.is_null()); | |
2572 return !other_constant->handle_.is_null() && | |
2573 *handle_ == *other_constant->handle_; | |
2574 } | |
2533 } | 2575 } |
2534 | 2576 |
2535 private: | 2577 private: |
2578 // We store the HConstant in the most specific form safely possible. | |
2579 // The two flags, has_int32_value_ and has_double_value_ tell us if | |
2580 // int32_value_ and double_value_ hold valid, safe representations | |
2581 // of the constant. has_int32_value_ implies has_double_value_ but | |
2582 // not the converse. | |
2583 | |
2584 // If this is a numerical constant, handle_ either points to to the | |
2585 // HeapObject the constant originated from or is null. If the | |
2586 // constant is non-numeric, handle_ always points to a valid | |
2587 // constant HeapObject. | |
2588 | |
2536 Handle<Object> handle_; | 2589 Handle<Object> handle_; |
2537 | 2590 |
2538 // The following two values represent the int32 and the double value of the | |
2539 // given constant if there is a lossless conversion between the constant | |
2540 // and the specific representation. | |
2541 bool has_int32_value_ : 1; | 2591 bool has_int32_value_ : 1; |
2542 bool has_double_value_ : 1; | 2592 bool has_double_value_ : 1; |
2593 bool handle_was_smi_ : 1; | |
2594 bool is_string_ : 1; | |
2595 bool is_symbol_ : 1; | |
2596 bool is_boolean_ : 1; | |
2543 int32_t int32_value_; | 2597 int32_t int32_value_; |
2544 double double_value_; | 2598 double double_value_; |
2545 }; | 2599 }; |
2546 | 2600 |
2547 | 2601 |
2548 class HBinaryOperation: public HTemplateInstruction<3> { | 2602 class HBinaryOperation: public HTemplateInstruction<3> { |
2549 public: | 2603 public: |
2550 HBinaryOperation(HValue* context, HValue* left, HValue* right) { | 2604 HBinaryOperation(HValue* context, HValue* left, HValue* right) { |
2551 ASSERT(left != NULL && right != NULL); | 2605 ASSERT(left != NULL && right != NULL); |
2552 SetOperandAt(0, context); | 2606 SetOperandAt(0, context); |
(...skipping 2544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5097 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex); | 5151 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex); |
5098 }; | 5152 }; |
5099 | 5153 |
5100 | 5154 |
5101 #undef DECLARE_INSTRUCTION | 5155 #undef DECLARE_INSTRUCTION |
5102 #undef DECLARE_CONCRETE_INSTRUCTION | 5156 #undef DECLARE_CONCRETE_INSTRUCTION |
5103 | 5157 |
5104 } } // namespace v8::internal | 5158 } } // namespace v8::internal |
5105 | 5159 |
5106 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 5160 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |