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 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 V(BackingStoreFields) \ | 204 V(BackingStoreFields) \ |
205 V(Calls) \ | 205 V(Calls) \ |
206 V(ContextSlots) \ | 206 V(ContextSlots) \ |
207 V(DoubleArrayElements) \ | 207 V(DoubleArrayElements) \ |
208 V(DoubleFields) \ | 208 V(DoubleFields) \ |
209 V(ElementsKind) \ | 209 V(ElementsKind) \ |
210 V(ElementsPointer) \ | 210 V(ElementsPointer) \ |
211 V(GlobalVars) \ | 211 V(GlobalVars) \ |
212 V(InobjectFields) \ | 212 V(InobjectFields) \ |
213 V(OsrEntries) \ | 213 V(OsrEntries) \ |
214 V(ExternalMemory) | 214 V(SpecializedArrayElements) |
215 | 215 |
216 | 216 |
217 #define DECLARE_ABSTRACT_INSTRUCTION(type) \ | 217 #define DECLARE_ABSTRACT_INSTRUCTION(type) \ |
218 virtual bool Is##type() const { return true; } \ | 218 virtual bool Is##type() const { return true; } \ |
219 static H##type* cast(HValue* value) { \ | 219 static H##type* cast(HValue* value) { \ |
220 ASSERT(value->Is##type()); \ | 220 ASSERT(value->Is##type()); \ |
221 return reinterpret_cast<H##type*>(value); \ | 221 return reinterpret_cast<H##type*>(value); \ |
222 } | 222 } |
223 | 223 |
224 | 224 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 return reinterpret_cast<intptr_t>(raw_address_); | 343 return reinterpret_cast<intptr_t>(raw_address_); |
344 } | 344 } |
345 | 345 |
346 private: | 346 private: |
347 Address raw_address_; | 347 Address raw_address_; |
348 }; | 348 }; |
349 | 349 |
350 | 350 |
351 class HType { | 351 class HType { |
352 public: | 352 public: |
353 static HType None() { return HType(kNone); } | 353 HType() : type_(kUninitialized) { } |
| 354 |
354 static HType Tagged() { return HType(kTagged); } | 355 static HType Tagged() { return HType(kTagged); } |
355 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); } | 356 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); } |
356 static HType TaggedNumber() { return HType(kTaggedNumber); } | 357 static HType TaggedNumber() { return HType(kTaggedNumber); } |
357 static HType Smi() { return HType(kSmi); } | 358 static HType Smi() { return HType(kSmi); } |
358 static HType HeapNumber() { return HType(kHeapNumber); } | 359 static HType HeapNumber() { return HType(kHeapNumber); } |
359 static HType String() { return HType(kString); } | 360 static HType String() { return HType(kString); } |
360 static HType Boolean() { return HType(kBoolean); } | 361 static HType Boolean() { return HType(kBoolean); } |
361 static HType NonPrimitive() { return HType(kNonPrimitive); } | 362 static HType NonPrimitive() { return HType(kNonPrimitive); } |
362 static HType JSArray() { return HType(kJSArray); } | 363 static HType JSArray() { return HType(kJSArray); } |
363 static HType JSObject() { return HType(kJSObject); } | 364 static HType JSObject() { return HType(kJSObject); } |
| 365 static HType Uninitialized() { return HType(kUninitialized); } |
364 | 366 |
365 // Return the weakest (least precise) common type. | 367 // Return the weakest (least precise) common type. |
366 HType Combine(HType other) { | 368 HType Combine(HType other) { |
367 return HType(static_cast<Type>(type_ & other.type_)); | 369 return HType(static_cast<Type>(type_ & other.type_)); |
368 } | 370 } |
369 | 371 |
370 bool Equals(const HType& other) const { | 372 bool Equals(const HType& other) const { |
371 return type_ == other.type_; | 373 return type_ == other.type_; |
372 } | 374 } |
373 | 375 |
374 bool IsSubtypeOf(const HType& other) { | 376 bool IsSubtypeOf(const HType& other) { |
375 return Combine(other).Equals(other); | 377 return Combine(other).Equals(other); |
376 } | 378 } |
377 | 379 |
378 bool IsTagged() const { | 380 bool IsTagged() const { |
| 381 ASSERT(type_ != kUninitialized); |
379 return ((type_ & kTagged) == kTagged); | 382 return ((type_ & kTagged) == kTagged); |
380 } | 383 } |
381 | 384 |
382 bool IsTaggedPrimitive() const { | 385 bool IsTaggedPrimitive() const { |
| 386 ASSERT(type_ != kUninitialized); |
383 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive); | 387 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive); |
384 } | 388 } |
385 | 389 |
386 bool IsTaggedNumber() const { | 390 bool IsTaggedNumber() const { |
| 391 ASSERT(type_ != kUninitialized); |
387 return ((type_ & kTaggedNumber) == kTaggedNumber); | 392 return ((type_ & kTaggedNumber) == kTaggedNumber); |
388 } | 393 } |
389 | 394 |
390 bool IsSmi() const { | 395 bool IsSmi() const { |
| 396 ASSERT(type_ != kUninitialized); |
391 return ((type_ & kSmi) == kSmi); | 397 return ((type_ & kSmi) == kSmi); |
392 } | 398 } |
393 | 399 |
394 bool IsHeapNumber() const { | 400 bool IsHeapNumber() const { |
| 401 ASSERT(type_ != kUninitialized); |
395 return ((type_ & kHeapNumber) == kHeapNumber); | 402 return ((type_ & kHeapNumber) == kHeapNumber); |
396 } | 403 } |
397 | 404 |
398 bool IsString() const { | 405 bool IsString() const { |
| 406 ASSERT(type_ != kUninitialized); |
399 return ((type_ & kString) == kString); | 407 return ((type_ & kString) == kString); |
400 } | 408 } |
401 | 409 |
402 bool IsNonString() const { | 410 bool IsNonString() const { |
403 return IsTaggedPrimitive() || IsSmi() || IsHeapNumber() || | 411 return IsTaggedPrimitive() || IsSmi() || IsHeapNumber() || |
404 IsBoolean() || IsJSArray(); | 412 IsBoolean() || IsJSArray(); |
405 } | 413 } |
406 | 414 |
407 bool IsBoolean() const { | 415 bool IsBoolean() const { |
| 416 ASSERT(type_ != kUninitialized); |
408 return ((type_ & kBoolean) == kBoolean); | 417 return ((type_ & kBoolean) == kBoolean); |
409 } | 418 } |
410 | 419 |
411 bool IsNonPrimitive() const { | 420 bool IsNonPrimitive() const { |
| 421 ASSERT(type_ != kUninitialized); |
412 return ((type_ & kNonPrimitive) == kNonPrimitive); | 422 return ((type_ & kNonPrimitive) == kNonPrimitive); |
413 } | 423 } |
414 | 424 |
415 bool IsJSArray() const { | 425 bool IsJSArray() const { |
| 426 ASSERT(type_ != kUninitialized); |
416 return ((type_ & kJSArray) == kJSArray); | 427 return ((type_ & kJSArray) == kJSArray); |
417 } | 428 } |
418 | 429 |
419 bool IsJSObject() const { | 430 bool IsJSObject() const { |
| 431 ASSERT(type_ != kUninitialized); |
420 return ((type_ & kJSObject) == kJSObject); | 432 return ((type_ & kJSObject) == kJSObject); |
421 } | 433 } |
422 | 434 |
| 435 bool IsUninitialized() const { |
| 436 return type_ == kUninitialized; |
| 437 } |
| 438 |
423 bool IsHeapObject() const { | 439 bool IsHeapObject() const { |
| 440 ASSERT(type_ != kUninitialized); |
424 return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive(); | 441 return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive(); |
425 } | 442 } |
426 | 443 |
427 bool ToStringOrToNumberCanBeObserved(Representation representation) { | |
428 switch (type_) { | |
429 case kTaggedPrimitive: // fallthru | |
430 case kTaggedNumber: // fallthru | |
431 case kSmi: // fallthru | |
432 case kHeapNumber: // fallthru | |
433 case kString: // fallthru | |
434 case kBoolean: | |
435 return false; | |
436 case kJSArray: // fallthru | |
437 case kJSObject: | |
438 return true; | |
439 case kTagged: | |
440 break; | |
441 } | |
442 return !representation.IsSmiOrInteger32() && !representation.IsDouble(); | |
443 } | |
444 | |
445 static HType TypeFromValue(Handle<Object> value); | 444 static HType TypeFromValue(Handle<Object> value); |
446 | 445 |
447 const char* ToString(); | 446 const char* ToString(); |
448 | 447 |
449 private: | 448 private: |
450 enum Type { | 449 enum Type { |
451 kNone = 0x0, // 0000 0000 0000 0000 | |
452 kTagged = 0x1, // 0000 0000 0000 0001 | 450 kTagged = 0x1, // 0000 0000 0000 0001 |
453 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101 | 451 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101 |
454 kTaggedNumber = 0xd, // 0000 0000 0000 1101 | 452 kTaggedNumber = 0xd, // 0000 0000 0000 1101 |
455 kSmi = 0x1d, // 0000 0000 0001 1101 | 453 kSmi = 0x1d, // 0000 0000 0001 1101 |
456 kHeapNumber = 0x2d, // 0000 0000 0010 1101 | 454 kHeapNumber = 0x2d, // 0000 0000 0010 1101 |
457 kString = 0x45, // 0000 0000 0100 0101 | 455 kString = 0x45, // 0000 0000 0100 0101 |
458 kBoolean = 0x85, // 0000 0000 1000 0101 | 456 kBoolean = 0x85, // 0000 0000 1000 0101 |
459 kNonPrimitive = 0x101, // 0000 0001 0000 0001 | 457 kNonPrimitive = 0x101, // 0000 0001 0000 0001 |
460 kJSObject = 0x301, // 0000 0011 0000 0001 | 458 kJSObject = 0x301, // 0000 0011 0000 0001 |
461 kJSArray = 0x701 // 0000 0111 0000 0001 | 459 kJSArray = 0x701, // 0000 0111 0000 0001 |
| 460 kUninitialized = 0x1fff // 0001 1111 1111 1111 |
462 }; | 461 }; |
463 | 462 |
464 // Make sure type fits in int16. | 463 // Make sure type fits in int16. |
465 STATIC_ASSERT(kJSArray < (1 << (2 * kBitsPerByte))); | 464 STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte))); |
466 | 465 |
467 explicit HType(Type t) : type_(t) { } | 466 explicit HType(Type t) : type_(t) { } |
468 | 467 |
469 int16_t type_; | 468 int16_t type_; |
470 }; | 469 }; |
471 | 470 |
472 | 471 |
473 class HUseListNode: public ZoneObject { | 472 class HUseListNode: public ZoneObject { |
474 public: | 473 public: |
475 HUseListNode(HValue* value, int index, HUseListNode* tail) | 474 HUseListNode(HValue* value, int index, HUseListNode* tail) |
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 | 1138 |
1140 bool TryGuaranteeRange(HValue* upper_bound); | 1139 bool TryGuaranteeRange(HValue* upper_bound); |
1141 virtual bool TryDecompose(DecompositionResult* decomposition) { | 1140 virtual bool TryDecompose(DecompositionResult* decomposition) { |
1142 if (RedefinedOperand() != NULL) { | 1141 if (RedefinedOperand() != NULL) { |
1143 return RedefinedOperand()->TryDecompose(decomposition); | 1142 return RedefinedOperand()->TryDecompose(decomposition); |
1144 } else { | 1143 } else { |
1145 return false; | 1144 return false; |
1146 } | 1145 } |
1147 } | 1146 } |
1148 | 1147 |
1149 // Returns true conservatively if the program might be able to observe a | |
1150 // ToString() operation on this value. | |
1151 bool ToStringCanBeObserved() const { | |
1152 return type().ToStringOrToNumberCanBeObserved(representation()); | |
1153 } | |
1154 | |
1155 // Returns true conservatively if the program might be able to observe a | |
1156 // ToNumber() operation on this value. | |
1157 bool ToNumberCanBeObserved() const { | |
1158 return type().ToStringOrToNumberCanBeObserved(representation()); | |
1159 } | |
1160 | |
1161 protected: | 1148 protected: |
1162 void TryGuaranteeRangeRecursive(RangeEvaluationContext* context); | 1149 void TryGuaranteeRangeRecursive(RangeEvaluationContext* context); |
1163 | 1150 |
1164 enum RangeGuaranteeDirection { | 1151 enum RangeGuaranteeDirection { |
1165 DIRECTION_NONE = 0, | 1152 DIRECTION_NONE = 0, |
1166 DIRECTION_UPPER = 1, | 1153 DIRECTION_UPPER = 1, |
1167 DIRECTION_LOWER = 2, | 1154 DIRECTION_LOWER = 2, |
1168 DIRECTION_BOTH = DIRECTION_UPPER | DIRECTION_LOWER | 1155 DIRECTION_BOTH = DIRECTION_UPPER | DIRECTION_LOWER |
1169 }; | 1156 }; |
1170 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {} | 1157 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {} |
(...skipping 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2688 // change. The external array of a specialized array elements object cannot | 2675 // change. The external array of a specialized array elements object cannot |
2689 // change once set, so it's no necessary to introduce any additional | 2676 // change once set, so it's no necessary to introduce any additional |
2690 // dependencies on top of the inputs. | 2677 // dependencies on top of the inputs. |
2691 SetFlag(kUseGVN); | 2678 SetFlag(kUseGVN); |
2692 } | 2679 } |
2693 | 2680 |
2694 virtual Representation RequiredInputRepresentation(int index) { | 2681 virtual Representation RequiredInputRepresentation(int index) { |
2695 return Representation::Tagged(); | 2682 return Representation::Tagged(); |
2696 } | 2683 } |
2697 | 2684 |
2698 virtual HType CalculateInferredType() { | |
2699 return HType::None(); | |
2700 } | |
2701 | |
2702 DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer) | 2685 DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer) |
2703 | 2686 |
2704 protected: | 2687 protected: |
2705 virtual bool DataEquals(HValue* other) { return true; } | 2688 virtual bool DataEquals(HValue* other) { return true; } |
2706 | 2689 |
2707 private: | 2690 private: |
2708 virtual bool IsDeletable() const { return true; } | 2691 virtual bool IsDeletable() const { return true; } |
2709 }; | 2692 }; |
2710 | 2693 |
2711 | 2694 |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2947 return Representation::Tagged(); | 2930 return Representation::Tagged(); |
2948 } | 2931 } |
2949 | 2932 |
2950 virtual HType CalculateInferredType(); | 2933 virtual HType CalculateInferredType(); |
2951 | 2934 |
2952 #ifdef DEBUG | 2935 #ifdef DEBUG |
2953 virtual void Verify(); | 2936 virtual void Verify(); |
2954 #endif | 2937 #endif |
2955 | 2938 |
2956 virtual HValue* Canonicalize() { | 2939 virtual HValue* Canonicalize() { |
2957 return value()->type().IsHeapObject() ? NULL : this; | 2940 HType value_type = value()->type(); |
| 2941 if (!value_type.IsUninitialized() && value_type.IsHeapObject()) { |
| 2942 return NULL; |
| 2943 } |
| 2944 return this; |
2958 } | 2945 } |
2959 | 2946 |
2960 DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject) | 2947 DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject) |
2961 | 2948 |
2962 protected: | 2949 protected: |
2963 virtual bool DataEquals(HValue* other) { return true; } | 2950 virtual bool DataEquals(HValue* other) { return true; } |
2964 }; | 2951 }; |
2965 | 2952 |
2966 | 2953 |
2967 class HCheckPrototypeMaps: public HTemplateInstruction<0> { | 2954 class HCheckPrototypeMaps: public HTemplateInstruction<0> { |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3349 int phi_id() { return phi_id_; } | 3336 int phi_id() { return phi_id_; } |
3350 | 3337 |
3351 static HPhi* cast(HValue* value) { | 3338 static HPhi* cast(HValue* value) { |
3352 ASSERT(value->IsPhi()); | 3339 ASSERT(value->IsPhi()); |
3353 return reinterpret_cast<HPhi*>(value); | 3340 return reinterpret_cast<HPhi*>(value); |
3354 } | 3341 } |
3355 virtual Opcode opcode() const { return HValue::kPhi; } | 3342 virtual Opcode opcode() const { return HValue::kPhi; } |
3356 | 3343 |
3357 void SimplifyConstantInputs(); | 3344 void SimplifyConstantInputs(); |
3358 | 3345 |
| 3346 // TODO(titzer): we can't eliminate the receiver for generating backtraces |
| 3347 virtual bool IsDeletable() const { return !IsReceiver(); } |
| 3348 |
3359 protected: | 3349 protected: |
3360 virtual void DeleteFromGraph(); | 3350 virtual void DeleteFromGraph(); |
3361 virtual void InternalSetOperandAt(int index, HValue* value) { | 3351 virtual void InternalSetOperandAt(int index, HValue* value) { |
3362 inputs_[index] = value; | 3352 inputs_[index] = value; |
3363 } | 3353 } |
3364 | 3354 |
3365 virtual bool IsRelationTrueInternal(NumericRelation relation, | 3355 virtual bool IsRelationTrueInternal(NumericRelation relation, |
3366 HValue* other, | 3356 HValue* other, |
3367 int offset = 0, | 3357 int offset = 0, |
3368 int scale = 0); | 3358 int scale = 0); |
3369 | 3359 |
3370 private: | 3360 private: |
3371 ZoneList<HValue*> inputs_; | 3361 ZoneList<HValue*> inputs_; |
3372 int merged_index_; | 3362 int merged_index_; |
3373 | 3363 |
3374 int non_phi_uses_[Representation::kNumRepresentations]; | 3364 int non_phi_uses_[Representation::kNumRepresentations]; |
3375 int indirect_uses_[Representation::kNumRepresentations]; | 3365 int indirect_uses_[Representation::kNumRepresentations]; |
3376 int phi_id_; | 3366 int phi_id_; |
3377 InductionVariableData* induction_variable_data_; | 3367 InductionVariableData* induction_variable_data_; |
3378 | |
3379 // TODO(titzer): we can't eliminate the receiver for generating backtraces | |
3380 virtual bool IsDeletable() const { return !IsReceiver(); } | |
3381 }; | 3368 }; |
3382 | 3369 |
3383 | 3370 |
3384 class HInductionVariableAnnotation : public HUnaryOperation { | 3371 class HInductionVariableAnnotation : public HUnaryOperation { |
3385 public: | 3372 public: |
3386 static HInductionVariableAnnotation* AddToGraph(HPhi* phi, | 3373 static HInductionVariableAnnotation* AddToGraph(HPhi* phi, |
3387 NumericRelation relation, | 3374 NumericRelation relation, |
3388 int operand_index); | 3375 int operand_index); |
3389 | 3376 |
3390 NumericRelation relation() { return relation_; } | 3377 NumericRelation relation() { return relation_; } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3477 bool is_not_in_new_space = true, | 3464 bool is_not_in_new_space = true, |
3478 Handle<Object> optional_handle = Handle<Object>::null()); | 3465 Handle<Object> optional_handle = Handle<Object>::null()); |
3479 HConstant(Handle<Object> handle, | 3466 HConstant(Handle<Object> handle, |
3480 UniqueValueId unique_id, | 3467 UniqueValueId unique_id, |
3481 Representation r, | 3468 Representation r, |
3482 HType type, | 3469 HType type, |
3483 bool is_internalized_string, | 3470 bool is_internalized_string, |
3484 bool is_not_in_new_space, | 3471 bool is_not_in_new_space, |
3485 bool is_cell, | 3472 bool is_cell, |
3486 bool boolean_value); | 3473 bool boolean_value); |
3487 explicit HConstant(ExternalReference reference); | |
3488 | 3474 |
3489 Handle<Object> handle() { | 3475 Handle<Object> handle() { |
3490 if (handle_.is_null()) { | 3476 if (handle_.is_null()) { |
3491 Factory* factory = Isolate::Current()->factory(); | 3477 Factory* factory = Isolate::Current()->factory(); |
3492 // Default arguments to is_not_in_new_space depend on this heap number | 3478 // Default arguments to is_not_in_new_space depend on this heap number |
3493 // to be tenured so that it's guaranteed not be be located in new space. | 3479 // to be tenured so that it's guaranteed not be be located in new space. |
3494 handle_ = factory->NewNumber(double_value_, TENURED); | 3480 handle_ = factory->NewNumber(double_value_, TENURED); |
3495 } | 3481 } |
3496 AllowDeferredHandleDereference smi_check; | 3482 AllowDeferredHandleDereference smi_check; |
3497 ASSERT(has_int32_value_ || !handle_->IsSmi()); | 3483 ASSERT(has_int32_value_ || !handle_->IsSmi()); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3542 } | 3528 } |
3543 | 3529 |
3544 virtual Representation RequiredInputRepresentation(int index) { | 3530 virtual Representation RequiredInputRepresentation(int index) { |
3545 return Representation::None(); | 3531 return Representation::None(); |
3546 } | 3532 } |
3547 | 3533 |
3548 virtual Representation KnownOptimalRepresentation() { | 3534 virtual Representation KnownOptimalRepresentation() { |
3549 if (HasSmiValue() && kSmiValueSize == 31) return Representation::Smi(); | 3535 if (HasSmiValue() && kSmiValueSize == 31) return Representation::Smi(); |
3550 if (HasInteger32Value()) return Representation::Integer32(); | 3536 if (HasInteger32Value()) return Representation::Integer32(); |
3551 if (HasNumberValue()) return Representation::Double(); | 3537 if (HasNumberValue()) return Representation::Double(); |
3552 if (HasExternalReferenceValue()) return Representation::External(); | |
3553 return Representation::Tagged(); | 3538 return Representation::Tagged(); |
3554 } | 3539 } |
3555 | 3540 |
3556 virtual bool EmitAtUses(); | 3541 virtual bool EmitAtUses(); |
3557 virtual void PrintDataTo(StringStream* stream); | 3542 virtual void PrintDataTo(StringStream* stream); |
| 3543 virtual HType CalculateInferredType(); |
3558 bool IsInteger() { return handle()->IsSmi(); } | 3544 bool IsInteger() { return handle()->IsSmi(); } |
3559 HConstant* CopyToRepresentation(Representation r, Zone* zone) const; | 3545 HConstant* CopyToRepresentation(Representation r, Zone* zone) const; |
3560 Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone); | 3546 Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone); |
3561 Maybe<HConstant*> CopyToTruncatedNumber(Zone* zone); | 3547 Maybe<HConstant*> CopyToTruncatedNumber(Zone* zone); |
3562 bool HasInteger32Value() const { return has_int32_value_; } | 3548 bool HasInteger32Value() const { return has_int32_value_; } |
3563 int32_t Integer32Value() const { | 3549 int32_t Integer32Value() const { |
3564 ASSERT(HasInteger32Value()); | 3550 ASSERT(HasInteger32Value()); |
3565 return int32_value_; | 3551 return int32_value_; |
3566 } | 3552 } |
3567 bool HasSmiValue() const { return has_smi_value_; } | 3553 bool HasSmiValue() const { return has_smi_value_; } |
(...skipping 16 matching lines...) Expand all Loading... |
3584 int32_t NumberValueAsInteger32() const { | 3570 int32_t NumberValueAsInteger32() const { |
3585 ASSERT(HasNumberValue()); | 3571 ASSERT(HasNumberValue()); |
3586 // Irrespective of whether a numeric HConstant can be safely | 3572 // Irrespective of whether a numeric HConstant can be safely |
3587 // represented as an int32, we store the (in some cases lossy) | 3573 // represented as an int32, we store the (in some cases lossy) |
3588 // representation of the number in int32_value_. | 3574 // representation of the number in int32_value_. |
3589 return int32_value_; | 3575 return int32_value_; |
3590 } | 3576 } |
3591 bool HasStringValue() const { | 3577 bool HasStringValue() const { |
3592 if (has_double_value_ || has_int32_value_) return false; | 3578 if (has_double_value_ || has_int32_value_) return false; |
3593 ASSERT(!handle_.is_null()); | 3579 ASSERT(!handle_.is_null()); |
3594 return type_.IsString(); | 3580 return type_from_value_.IsString(); |
3595 } | 3581 } |
3596 Handle<String> StringValue() const { | 3582 Handle<String> StringValue() const { |
3597 ASSERT(HasStringValue()); | 3583 ASSERT(HasStringValue()); |
3598 return Handle<String>::cast(handle_); | 3584 return Handle<String>::cast(handle_); |
3599 } | 3585 } |
3600 bool HasInternalizedStringValue() const { | 3586 bool HasInternalizedStringValue() const { |
3601 return HasStringValue() && is_internalized_string_; | 3587 return HasStringValue() && is_internalized_string_; |
3602 } | 3588 } |
3603 | 3589 |
3604 bool HasExternalReferenceValue() const { | |
3605 return has_external_reference_value_; | |
3606 } | |
3607 ExternalReference ExternalReferenceValue() const { | |
3608 return external_reference_value_; | |
3609 } | |
3610 | |
3611 bool BooleanValue() const { return boolean_value_; } | 3590 bool BooleanValue() const { return boolean_value_; } |
3612 | 3591 |
3613 virtual intptr_t Hashcode() { | 3592 virtual intptr_t Hashcode() { |
3614 if (has_int32_value_) { | 3593 if (has_int32_value_) { |
3615 return static_cast<intptr_t>(int32_value_); | 3594 return static_cast<intptr_t>(int32_value_); |
3616 } else if (has_double_value_) { | 3595 } else if (has_double_value_) { |
3617 return static_cast<intptr_t>(BitCast<int64_t>(double_value_)); | 3596 return static_cast<intptr_t>(BitCast<int64_t>(double_value_)); |
3618 } else if (has_external_reference_value_) { | |
3619 return reinterpret_cast<intptr_t>(external_reference_value_.address()); | |
3620 } else { | 3597 } else { |
3621 ASSERT(!handle_.is_null()); | 3598 ASSERT(!handle_.is_null()); |
3622 return unique_id_.Hashcode(); | 3599 return unique_id_.Hashcode(); |
3623 } | 3600 } |
3624 } | 3601 } |
3625 | 3602 |
3626 virtual void FinalizeUniqueValueId() { | 3603 virtual void FinalizeUniqueValueId() { |
3627 if (!has_double_value_ && !has_external_reference_value_) { | 3604 if (!has_double_value_) { |
3628 ASSERT(!handle_.is_null()); | 3605 ASSERT(!handle_.is_null()); |
3629 unique_id_ = UniqueValueId(handle_); | 3606 unique_id_ = UniqueValueId(handle_); |
3630 } | 3607 } |
3631 } | 3608 } |
3632 | 3609 |
3633 bool UniqueValueIdsMatch(UniqueValueId other) { | 3610 bool UniqueValueIdsMatch(UniqueValueId other) { |
3634 return !has_double_value_ && !has_external_reference_value_ && | 3611 return !has_double_value_ && unique_id_ == other; |
3635 unique_id_ == other; | |
3636 } | 3612 } |
3637 | 3613 |
3638 #ifdef DEBUG | 3614 #ifdef DEBUG |
3639 virtual void Verify() { } | 3615 virtual void Verify() { } |
3640 #endif | 3616 #endif |
3641 | 3617 |
3642 DECLARE_CONCRETE_INSTRUCTION(Constant) | 3618 DECLARE_CONCRETE_INSTRUCTION(Constant) |
3643 | 3619 |
3644 protected: | 3620 protected: |
3645 virtual Range* InferRange(Zone* zone); | 3621 virtual Range* InferRange(Zone* zone); |
3646 | 3622 |
3647 virtual bool DataEquals(HValue* other) { | 3623 virtual bool DataEquals(HValue* other) { |
3648 HConstant* other_constant = HConstant::cast(other); | 3624 HConstant* other_constant = HConstant::cast(other); |
3649 if (has_int32_value_) { | 3625 if (has_int32_value_) { |
3650 return other_constant->has_int32_value_ && | 3626 return other_constant->has_int32_value_ && |
3651 int32_value_ == other_constant->int32_value_; | 3627 int32_value_ == other_constant->int32_value_; |
3652 } else if (has_double_value_) { | 3628 } else if (has_double_value_) { |
3653 return other_constant->has_double_value_ && | 3629 return other_constant->has_double_value_ && |
3654 BitCast<int64_t>(double_value_) == | 3630 BitCast<int64_t>(double_value_) == |
3655 BitCast<int64_t>(other_constant->double_value_); | 3631 BitCast<int64_t>(other_constant->double_value_); |
3656 } else if (has_external_reference_value_) { | |
3657 return other_constant->has_external_reference_value_ && | |
3658 external_reference_value_ == | |
3659 other_constant->external_reference_value_; | |
3660 } else { | 3632 } else { |
3661 ASSERT(!handle_.is_null()); | 3633 ASSERT(!handle_.is_null()); |
3662 return !other_constant->handle_.is_null() && | 3634 return !other_constant->handle_.is_null() && |
3663 unique_id_ == other_constant->unique_id_; | 3635 unique_id_ == other_constant->unique_id_; |
3664 } | 3636 } |
3665 } | 3637 } |
3666 | 3638 |
3667 private: | 3639 private: |
3668 void Initialize(Representation r); | 3640 void Initialize(Representation r); |
3669 | 3641 |
3670 virtual bool IsDeletable() const { return true; } | 3642 virtual bool IsDeletable() const { return true; } |
3671 | 3643 |
3672 // If this is a numerical constant, handle_ either points to to the | 3644 // If this is a numerical constant, handle_ either points to to the |
3673 // HeapObject the constant originated from or is null. If the | 3645 // HeapObject the constant originated from or is null. If the |
3674 // constant is non-numeric, handle_ always points to a valid | 3646 // constant is non-numeric, handle_ always points to a valid |
3675 // constant HeapObject. | 3647 // constant HeapObject. |
3676 Handle<Object> handle_; | 3648 Handle<Object> handle_; |
3677 UniqueValueId unique_id_; | 3649 UniqueValueId unique_id_; |
3678 | 3650 |
3679 // We store the HConstant in the most specific form safely possible. | 3651 // We store the HConstant in the most specific form safely possible. |
3680 // The two flags, has_int32_value_ and has_double_value_ tell us if | 3652 // The two flags, has_int32_value_ and has_double_value_ tell us if |
3681 // int32_value_ and double_value_ hold valid, safe representations | 3653 // int32_value_ and double_value_ hold valid, safe representations |
3682 // of the constant. has_int32_value_ implies has_double_value_ but | 3654 // of the constant. has_int32_value_ implies has_double_value_ but |
3683 // not the converse. | 3655 // not the converse. |
3684 bool has_smi_value_ : 1; | 3656 bool has_smi_value_ : 1; |
3685 bool has_int32_value_ : 1; | 3657 bool has_int32_value_ : 1; |
3686 bool has_double_value_ : 1; | 3658 bool has_double_value_ : 1; |
3687 bool has_external_reference_value_ : 1; | |
3688 bool is_internalized_string_ : 1; // TODO(yangguo): make this part of HType. | 3659 bool is_internalized_string_ : 1; // TODO(yangguo): make this part of HType. |
3689 bool is_not_in_new_space_ : 1; | 3660 bool is_not_in_new_space_ : 1; |
3690 bool is_cell_ : 1; | 3661 bool is_cell_ : 1; |
3691 bool boolean_value_ : 1; | 3662 bool boolean_value_ : 1; |
3692 int32_t int32_value_; | 3663 int32_t int32_value_; |
3693 double double_value_; | 3664 double double_value_; |
3694 ExternalReference external_reference_value_; | 3665 HType type_from_value_; |
3695 }; | 3666 }; |
3696 | 3667 |
3697 | 3668 |
3698 class HBinaryOperation: public HTemplateInstruction<3> { | 3669 class HBinaryOperation: public HTemplateInstruction<3> { |
3699 public: | 3670 public: |
3700 HBinaryOperation(HValue* context, HValue* left, HValue* right) | 3671 HBinaryOperation(HValue* context, HValue* left, HValue* right) |
3701 : observed_output_representation_(Representation::None()) { | 3672 : observed_output_representation_(Representation::None()) { |
3702 ASSERT(left != NULL && right != NULL); | 3673 ASSERT(left != NULL && right != NULL); |
3703 SetOperandAt(0, context); | 3674 SetOperandAt(0, context); |
3704 SetOperandAt(1, left); | 3675 SetOperandAt(1, left); |
3705 SetOperandAt(2, right); | 3676 SetOperandAt(2, right); |
3706 observed_input_representation_[0] = Representation::None(); | 3677 observed_input_representation_[0] = Representation::None(); |
3707 observed_input_representation_[1] = Representation::None(); | 3678 observed_input_representation_[1] = Representation::None(); |
3708 } | 3679 } |
3709 | 3680 |
3710 HValue* context() const { return OperandAt(0); } | 3681 HValue* context() { return OperandAt(0); } |
3711 HValue* left() const { return OperandAt(1); } | 3682 HValue* left() { return OperandAt(1); } |
3712 HValue* right() const { return OperandAt(2); } | 3683 HValue* right() { return OperandAt(2); } |
3713 | 3684 |
3714 // True if switching left and right operands likely generates better code. | 3685 // True if switching left and right operands likely generates better code. |
3715 bool AreOperandsBetterSwitched() { | 3686 bool AreOperandsBetterSwitched() { |
3716 if (!IsCommutative()) return false; | 3687 if (!IsCommutative()) return false; |
3717 | 3688 |
3718 // Constant operands are better off on the right, they can be inlined in | 3689 // Constant operands are better off on the right, they can be inlined in |
3719 // many situations on most platforms. | 3690 // many situations on most platforms. |
3720 if (left()->IsConstant()) return true; | 3691 if (left()->IsConstant()) return true; |
3721 if (right()->IsConstant()) return false; | 3692 if (right()->IsConstant()) return false; |
3722 | 3693 |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3956 base_ = index(); | 3927 base_ = index(); |
3957 offset_ = 0; | 3928 offset_ = 0; |
3958 scale_ = 0; | 3929 scale_ = 0; |
3959 return false; | 3930 return false; |
3960 } | 3931 } |
3961 } | 3932 } |
3962 | 3933 |
3963 virtual Representation RequiredInputRepresentation(int arg_index) { | 3934 virtual Representation RequiredInputRepresentation(int arg_index) { |
3964 return representation(); | 3935 return representation(); |
3965 } | 3936 } |
| 3937 virtual bool IsDeletable() const { |
| 3938 return skip_check() && !FLAG_debug_code; |
| 3939 } |
3966 | 3940 |
3967 virtual bool IsRelationTrueInternal(NumericRelation relation, | 3941 virtual bool IsRelationTrueInternal(NumericRelation relation, |
3968 HValue* related_value, | 3942 HValue* related_value, |
3969 int offset = 0, | 3943 int offset = 0, |
3970 int scale = 0); | 3944 int scale = 0); |
3971 | 3945 |
3972 virtual void PrintDataTo(StringStream* stream); | 3946 virtual void PrintDataTo(StringStream* stream); |
3973 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); | 3947 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
3974 | 3948 |
3975 HValue* index() { return OperandAt(0); } | 3949 HValue* index() { return OperandAt(0); } |
(...skipping 16 matching lines...) Expand all Loading... |
3992 } | 3966 } |
3993 | 3967 |
3994 virtual bool DataEquals(HValue* other) { return true; } | 3968 virtual bool DataEquals(HValue* other) { return true; } |
3995 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); | 3969 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); |
3996 bool skip_check_; | 3970 bool skip_check_; |
3997 HValue* base_; | 3971 HValue* base_; |
3998 int offset_; | 3972 int offset_; |
3999 int scale_; | 3973 int scale_; |
4000 RangeGuaranteeDirection responsibility_direction_; | 3974 RangeGuaranteeDirection responsibility_direction_; |
4001 bool allow_equality_; | 3975 bool allow_equality_; |
4002 | |
4003 private: | |
4004 virtual bool IsDeletable() const { | |
4005 return skip_check() && !FLAG_debug_code; | |
4006 } | |
4007 }; | 3976 }; |
4008 | 3977 |
4009 | 3978 |
4010 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { | 3979 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { |
4011 public: | 3980 public: |
4012 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { | 3981 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { |
4013 DecompositionResult decomposition; | 3982 DecompositionResult decomposition; |
4014 if (check->index()->TryDecompose(&decomposition)) { | 3983 if (check->index()->TryDecompose(&decomposition)) { |
4015 SetOperandAt(0, decomposition.base()); | 3984 SetOperandAt(0, decomposition.base()); |
4016 SetOperandAt(1, check); | 3985 SetOperandAt(1, check); |
(...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4816 | 4785 |
4817 virtual Representation observed_input_representation(int index) { | 4786 virtual Representation observed_input_representation(int index) { |
4818 return RequiredInputRepresentation(index); | 4787 return RequiredInputRepresentation(index); |
4819 } | 4788 } |
4820 | 4789 |
4821 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); | 4790 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
4822 | 4791 |
4823 virtual Representation RepresentationFromInputs() { | 4792 virtual Representation RepresentationFromInputs() { |
4824 Representation left_rep = left()->representation(); | 4793 Representation left_rep = left()->representation(); |
4825 Representation right_rep = right()->representation(); | 4794 Representation right_rep = right()->representation(); |
4826 Representation result = Representation::Smi(); | 4795 // TODO(verwaest): Initialize to Smi once lithium-codegen has been fixed. |
| 4796 Representation result = Representation::Integer32(); |
4827 result = result.generalize(left_rep); | 4797 result = result.generalize(left_rep); |
4828 result = result.generalize(right_rep); | 4798 result = result.generalize(right_rep); |
4829 if (result.IsTagged()) return Representation::Double(); | 4799 if (result.IsTagged()) return Representation::Double(); |
4830 return result; | 4800 return result; |
4831 } | 4801 } |
4832 | 4802 |
4833 virtual bool IsCommutative() const { return true; } | 4803 virtual bool IsCommutative() const { return true; } |
4834 | 4804 |
4835 Operation operation() { return operation_; } | 4805 Operation operation() { return operation_; } |
4836 | 4806 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4914 static HInstruction* New(Zone* zone, | 4884 static HInstruction* New(Zone* zone, |
4915 HValue* context, | 4885 HValue* context, |
4916 HValue* left, | 4886 HValue* left, |
4917 HValue* right); | 4887 HValue* right); |
4918 | 4888 |
4919 virtual Range* InferRange(Zone* zone); | 4889 virtual Range* InferRange(Zone* zone); |
4920 | 4890 |
4921 virtual void UpdateRepresentation(Representation new_rep, | 4891 virtual void UpdateRepresentation(Representation new_rep, |
4922 HInferRepresentationPhase* h_infer, | 4892 HInferRepresentationPhase* h_infer, |
4923 const char* reason) { | 4893 const char* reason) { |
4924 if (new_rep.IsSmi() && | 4894 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); |
4925 !(right()->IsInteger32Constant() && | |
4926 right()->GetInteger32Constant() >= 0)) { | |
4927 new_rep = Representation::Integer32(); | |
4928 } | |
4929 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 4895 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
4930 } | 4896 } |
4931 | 4897 |
4932 DECLARE_CONCRETE_INSTRUCTION(Shl) | 4898 DECLARE_CONCRETE_INSTRUCTION(Shl) |
4933 | 4899 |
4934 protected: | 4900 protected: |
4935 virtual bool DataEquals(HValue* other) { return true; } | 4901 virtual bool DataEquals(HValue* other) { return true; } |
4936 | 4902 |
4937 private: | 4903 private: |
4938 HShl(HValue* context, HValue* left, HValue* right) | 4904 HShl(HValue* context, HValue* left, HValue* right) |
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5581 int slot_index_; | 5547 int slot_index_; |
5582 Mode mode_; | 5548 Mode mode_; |
5583 }; | 5549 }; |
5584 | 5550 |
5585 | 5551 |
5586 // Represents an access to a portion of an object, such as the map pointer, | 5552 // Represents an access to a portion of an object, such as the map pointer, |
5587 // array elements pointer, etc, but not accesses to array elements themselves. | 5553 // array elements pointer, etc, but not accesses to array elements themselves. |
5588 class HObjectAccess { | 5554 class HObjectAccess { |
5589 public: | 5555 public: |
5590 inline bool IsInobject() const { | 5556 inline bool IsInobject() const { |
5591 return portion() != kBackingStore && portion() != kExternalMemory; | 5557 return portion() != kBackingStore; |
5592 } | |
5593 | |
5594 inline bool IsExternalMemory() const { | |
5595 return portion() == kExternalMemory; | |
5596 } | 5558 } |
5597 | 5559 |
5598 inline int offset() const { | 5560 inline int offset() const { |
5599 return OffsetField::decode(value_); | 5561 return OffsetField::decode(value_); |
5600 } | 5562 } |
5601 | 5563 |
5602 inline Representation representation() const { | 5564 inline Representation representation() const { |
5603 return Representation::FromKind(RepresentationField::decode(value_)); | 5565 return Representation::FromKind(RepresentationField::decode(value_)); |
5604 } | 5566 } |
5605 | 5567 |
5606 inline Handle<String> name() const { | 5568 inline Handle<String> name() const { |
5607 return name_; | 5569 return name_; |
5608 } | 5570 } |
5609 | 5571 |
5610 inline HObjectAccess WithRepresentation(Representation representation) { | 5572 inline HObjectAccess WithRepresentation(Representation representation) { |
5611 return HObjectAccess(portion(), offset(), representation, name()); | 5573 return HObjectAccess(portion(), offset(), representation, name()); |
5612 } | 5574 } |
5613 | 5575 |
5614 static HObjectAccess ForHeapNumberValue() { | 5576 static HObjectAccess ForHeapNumberValue() { |
5615 return HObjectAccess( | 5577 return HObjectAccess( |
5616 kDouble, HeapNumber::kValueOffset, Representation::Double()); | 5578 kDouble, HeapNumber::kValueOffset, Representation::Double()); |
5617 } | 5579 } |
5618 | 5580 |
5619 static HObjectAccess ForElementsPointer() { | 5581 static HObjectAccess ForElementsPointer() { |
5620 return HObjectAccess(kElementsPointer, JSObject::kElementsOffset); | 5582 return HObjectAccess(kElementsPointer, JSObject::kElementsOffset); |
5621 } | 5583 } |
5622 | 5584 |
5623 static HObjectAccess ForArrayLength(ElementsKind elements_kind) { | 5585 static HObjectAccess ForArrayLength(ElementsKind elements_kind) { |
5624 return HObjectAccess( | 5586 return HObjectAccess( |
5625 kArrayLengths, | 5587 kArrayLengths, JSArray::kLengthOffset, |
5626 JSArray::kLengthOffset, | 5588 IsFastElementsKind(elements_kind) && FLAG_track_fields ? |
5627 IsFastElementsKind(elements_kind) && | 5589 Representation::Smi() : Representation::Tagged()); |
5628 FLAG_track_fields | |
5629 ? Representation::Smi() : Representation::Tagged()); | |
5630 } | 5590 } |
5631 | 5591 |
5632 static HObjectAccess ForAllocationSiteTransitionInfo() { | 5592 static HObjectAccess ForAllocationSiteTransitionInfo() { |
5633 return HObjectAccess(kInobject, AllocationSite::kTransitionInfoOffset); | 5593 return HObjectAccess(kInobject, AllocationSite::kTransitionInfoOffset); |
5634 } | 5594 } |
5635 | 5595 |
5636 static HObjectAccess ForAllocationSiteWeakNext() { | 5596 static HObjectAccess ForAllocationSiteWeakNext() { |
5637 return HObjectAccess(kInobject, AllocationSite::kWeakNextOffset); | 5597 return HObjectAccess(kInobject, AllocationSite::kWeakNextOffset); |
5638 } | 5598 } |
5639 | 5599 |
5640 static HObjectAccess ForFixedArrayLength() { | 5600 static HObjectAccess ForFixedArrayLength() { |
5641 return HObjectAccess( | 5601 return HObjectAccess( |
5642 kArrayLengths, | 5602 kArrayLengths, FixedArray::kLengthOffset, |
5643 FixedArray::kLengthOffset, | 5603 FLAG_track_fields ? |
5644 FLAG_track_fields ? Representation::Smi() : Representation::Tagged()); | 5604 Representation::Smi() : Representation::Tagged()); |
5645 } | 5605 } |
5646 | 5606 |
5647 static HObjectAccess ForPropertiesPointer() { | 5607 static HObjectAccess ForPropertiesPointer() { |
5648 return HObjectAccess(kInobject, JSObject::kPropertiesOffset); | 5608 return HObjectAccess(kInobject, JSObject::kPropertiesOffset); |
5649 } | 5609 } |
5650 | 5610 |
5651 static HObjectAccess ForPrototypeOrInitialMap() { | 5611 static HObjectAccess ForPrototypeOrInitialMap() { |
5652 return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset); | 5612 return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset); |
5653 } | 5613 } |
5654 | 5614 |
5655 static HObjectAccess ForMap() { | 5615 static HObjectAccess ForMap() { |
5656 return HObjectAccess(kMaps, JSObject::kMapOffset); | 5616 return HObjectAccess(kMaps, JSObject::kMapOffset); |
5657 } | 5617 } |
5658 | 5618 |
5659 static HObjectAccess ForPropertyCellValue() { | 5619 static HObjectAccess ForPropertyCellValue() { |
5660 return HObjectAccess(kInobject, PropertyCell::kValueOffset); | 5620 return HObjectAccess(kInobject, PropertyCell::kValueOffset); |
5661 } | 5621 } |
5662 | 5622 |
5663 static HObjectAccess ForCellValue() { | 5623 static HObjectAccess ForCellValue() { |
5664 return HObjectAccess(kInobject, Cell::kValueOffset); | 5624 return HObjectAccess(kInobject, Cell::kValueOffset); |
5665 } | 5625 } |
5666 | 5626 |
5667 static HObjectAccess ForAllocationMementoSite() { | 5627 static HObjectAccess ForAllocationMementoSite() { |
5668 return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset); | 5628 return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset); |
5669 } | 5629 } |
5670 | 5630 |
5671 static HObjectAccess ForCounter() { | |
5672 return HObjectAccess(kExternalMemory, 0, Representation::Integer32()); | |
5673 } | |
5674 | |
5675 // Create an access to an offset in a fixed array header. | 5631 // Create an access to an offset in a fixed array header. |
5676 static HObjectAccess ForFixedArrayHeader(int offset); | 5632 static HObjectAccess ForFixedArrayHeader(int offset); |
5677 | 5633 |
5678 // Create an access to an in-object property in a JSObject. | 5634 // Create an access to an in-object property in a JSObject. |
5679 static HObjectAccess ForJSObjectOffset(int offset, | 5635 static HObjectAccess ForJSObjectOffset(int offset, |
5680 Representation representation = Representation::Tagged()); | 5636 Representation representation = Representation::Tagged()); |
5681 | 5637 |
5682 // Create an access to an in-object property in a JSArray. | 5638 // Create an access to an in-object property in a JSArray. |
5683 static HObjectAccess ForJSArrayOffset(int offset); | 5639 static HObjectAccess ForJSArrayOffset(int offset); |
5684 | 5640 |
(...skipping 18 matching lines...) Expand all Loading... |
5703 void SetGVNFlags(HValue *instr, bool is_store); | 5659 void SetGVNFlags(HValue *instr, bool is_store); |
5704 | 5660 |
5705 private: | 5661 private: |
5706 // internal use only; different parts of an object or array | 5662 // internal use only; different parts of an object or array |
5707 enum Portion { | 5663 enum Portion { |
5708 kMaps, // map of an object | 5664 kMaps, // map of an object |
5709 kArrayLengths, // the length of an array | 5665 kArrayLengths, // the length of an array |
5710 kElementsPointer, // elements pointer | 5666 kElementsPointer, // elements pointer |
5711 kBackingStore, // some field in the backing store | 5667 kBackingStore, // some field in the backing store |
5712 kDouble, // some double field | 5668 kDouble, // some double field |
5713 kInobject, // some other in-object field | 5669 kInobject // some other in-object field |
5714 kExternalMemory // some field in external memory | |
5715 }; | 5670 }; |
5716 | 5671 |
5717 HObjectAccess(Portion portion, int offset, | 5672 HObjectAccess(Portion portion, int offset, |
5718 Representation representation = Representation::Tagged(), | 5673 Representation representation = Representation::Tagged(), |
5719 Handle<String> name = Handle<String>::null()) | 5674 Handle<String> name = Handle<String>::null()) |
5720 : value_(PortionField::encode(portion) | | 5675 : value_(PortionField::encode(portion) | |
5721 RepresentationField::encode(representation.kind()) | | 5676 RepresentationField::encode(representation.kind()) | |
5722 OffsetField::encode(offset)), | 5677 OffsetField::encode(offset)), |
5723 name_(name) { | 5678 name_(name) { |
5724 // assert that the fields decode correctly | 5679 // assert that the fields decode correctly |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5782 HValue* typecheck = NULL) | 5737 HValue* typecheck = NULL) |
5783 : access_(access) { | 5738 : access_(access) { |
5784 ASSERT(object != NULL); | 5739 ASSERT(object != NULL); |
5785 SetOperandAt(0, object); | 5740 SetOperandAt(0, object); |
5786 SetOperandAt(1, typecheck != NULL ? typecheck : object); | 5741 SetOperandAt(1, typecheck != NULL ? typecheck : object); |
5787 | 5742 |
5788 Representation representation = access.representation(); | 5743 Representation representation = access.representation(); |
5789 if (representation.IsSmi()) { | 5744 if (representation.IsSmi()) { |
5790 set_type(HType::Smi()); | 5745 set_type(HType::Smi()); |
5791 set_representation(representation); | 5746 set_representation(representation); |
5792 } else if (representation.IsDouble() || | 5747 } else if (representation.IsDouble()) { |
5793 representation.IsExternal() || | |
5794 representation.IsInteger32()) { | |
5795 set_representation(representation); | 5748 set_representation(representation); |
5796 } else if (FLAG_track_heap_object_fields && | 5749 } else if (FLAG_track_heap_object_fields && |
5797 representation.IsHeapObject()) { | 5750 representation.IsHeapObject()) { |
5798 set_type(HType::NonPrimitive()); | 5751 set_type(HType::NonPrimitive()); |
5799 set_representation(Representation::Tagged()); | 5752 set_representation(Representation::Tagged()); |
5800 } else { | 5753 } else { |
5801 set_representation(Representation::Tagged()); | 5754 set_representation(Representation::Tagged()); |
5802 } | 5755 } |
5803 access.SetGVNFlags(this, false); | 5756 access.SetGVNFlags(this, false); |
5804 } | 5757 } |
5805 | 5758 |
5806 HValue* object() { return OperandAt(0); } | 5759 HValue* object() { return OperandAt(0); } |
5807 HValue* typecheck() { | 5760 HValue* typecheck() { |
5808 ASSERT(HasTypeCheck()); | 5761 ASSERT(HasTypeCheck()); |
5809 return OperandAt(1); | 5762 return OperandAt(1); |
5810 } | 5763 } |
5811 | 5764 |
5812 bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); } | 5765 bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); } |
5813 HObjectAccess access() const { return access_; } | 5766 HObjectAccess access() const { return access_; } |
5814 Representation field_representation() const { | 5767 Representation field_representation() const { |
5815 return access_.representation(); | 5768 return access_.representation(); |
5816 } | 5769 } |
5817 | 5770 |
5818 virtual bool HasEscapingOperandAt(int index) { return false; } | 5771 virtual bool HasEscapingOperandAt(int index) { return false; } |
5819 virtual Representation RequiredInputRepresentation(int index) { | 5772 virtual Representation RequiredInputRepresentation(int index) { |
5820 if (index == 0 && access().IsExternalMemory()) { | |
5821 // object must be external in case of external memory access | |
5822 return Representation::External(); | |
5823 } | |
5824 return Representation::Tagged(); | 5773 return Representation::Tagged(); |
5825 } | 5774 } |
5826 virtual void PrintDataTo(StringStream* stream); | 5775 virtual void PrintDataTo(StringStream* stream); |
5827 | 5776 |
5828 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField) | 5777 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField) |
5829 | 5778 |
5830 protected: | 5779 protected: |
5831 virtual bool DataEquals(HValue* other) { | 5780 virtual bool DataEquals(HValue* other) { |
5832 HLoadNamedField* b = HLoadNamedField::cast(other); | 5781 HLoadNamedField* b = HLoadNamedField::cast(other); |
5833 return access_.Equals(b->access_); | 5782 return access_.Equals(b->access_); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5987 SetGVNFlag(kDependsOnDoubleArrayElements); | 5936 SetGVNFlag(kDependsOnDoubleArrayElements); |
5988 } | 5937 } |
5989 } else { | 5938 } else { |
5990 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 5939 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
5991 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 5940 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
5992 set_representation(Representation::Double()); | 5941 set_representation(Representation::Double()); |
5993 } else { | 5942 } else { |
5994 set_representation(Representation::Integer32()); | 5943 set_representation(Representation::Integer32()); |
5995 } | 5944 } |
5996 | 5945 |
5997 SetGVNFlag(kDependsOnExternalMemory); | 5946 SetGVNFlag(kDependsOnSpecializedArrayElements); |
5998 // Native code could change the specialized array. | 5947 // Native code could change the specialized array. |
5999 SetGVNFlag(kDependsOnCalls); | 5948 SetGVNFlag(kDependsOnCalls); |
6000 } | 5949 } |
6001 | 5950 |
6002 SetFlag(kUseGVN); | 5951 SetFlag(kUseGVN); |
6003 } | 5952 } |
6004 | 5953 |
6005 bool is_external() const { | 5954 bool is_external() const { |
6006 return IsExternalArrayElementsKind(elements_kind()); | 5955 return IsExternalArrayElementsKind(elements_kind()); |
6007 } | 5956 } |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6144 write_barrier_mode_(UPDATE_WRITE_BARRIER) { | 6093 write_barrier_mode_(UPDATE_WRITE_BARRIER) { |
6145 SetOperandAt(0, obj); | 6094 SetOperandAt(0, obj); |
6146 SetOperandAt(1, val); | 6095 SetOperandAt(1, val); |
6147 access.SetGVNFlags(this, true); | 6096 access.SetGVNFlags(this, true); |
6148 } | 6097 } |
6149 | 6098 |
6150 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) | 6099 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) |
6151 | 6100 |
6152 virtual bool HasEscapingOperandAt(int index) { return index == 1; } | 6101 virtual bool HasEscapingOperandAt(int index) { return index == 1; } |
6153 virtual Representation RequiredInputRepresentation(int index) { | 6102 virtual Representation RequiredInputRepresentation(int index) { |
6154 if (index == 0 && access().IsExternalMemory()) { | 6103 if (index == 1 && field_representation().IsDouble()) { |
6155 // object must be external in case of external memory access | 6104 return field_representation(); |
6156 return Representation::External(); | 6105 } else if (index == 1 && field_representation().IsSmi()) { |
6157 } else if (index == 1 && | |
6158 (field_representation().IsDouble() || | |
6159 field_representation().IsSmi() || | |
6160 field_representation().IsInteger32())) { | |
6161 return field_representation(); | 6106 return field_representation(); |
6162 } | 6107 } |
6163 return Representation::Tagged(); | 6108 return Representation::Tagged(); |
6164 } | 6109 } |
6165 virtual void HandleSideEffectDominator(GVNFlag side_effect, | 6110 virtual void HandleSideEffectDominator(GVNFlag side_effect, |
6166 HValue* dominator) { | 6111 HValue* dominator) { |
6167 ASSERT(side_effect == kChangesNewSpacePromotion); | 6112 ASSERT(side_effect == kChangesNewSpacePromotion); |
6168 new_space_dominator_ = dominator; | 6113 new_space_dominator_ = dominator; |
6169 } | 6114 } |
6170 virtual void PrintDataTo(StringStream* stream); | 6115 virtual void PrintDataTo(StringStream* stream); |
(...skipping 17 matching lines...) Expand all Loading... |
6188 transition_ = map; | 6133 transition_ = map; |
6189 } | 6134 } |
6190 HValue* new_space_dominator() const { return new_space_dominator_; } | 6135 HValue* new_space_dominator() const { return new_space_dominator_; } |
6191 | 6136 |
6192 bool NeedsWriteBarrier() { | 6137 bool NeedsWriteBarrier() { |
6193 ASSERT(!(FLAG_track_double_fields && field_representation().IsDouble()) || | 6138 ASSERT(!(FLAG_track_double_fields && field_representation().IsDouble()) || |
6194 transition_.is_null()); | 6139 transition_.is_null()); |
6195 if (IsSkipWriteBarrier()) return false; | 6140 if (IsSkipWriteBarrier()) return false; |
6196 if (field_representation().IsDouble()) return false; | 6141 if (field_representation().IsDouble()) return false; |
6197 if (field_representation().IsSmi()) return false; | 6142 if (field_representation().IsSmi()) return false; |
6198 if (field_representation().IsInteger32()) return false; | |
6199 return StoringValueNeedsWriteBarrier(value()) && | 6143 return StoringValueNeedsWriteBarrier(value()) && |
6200 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); | 6144 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); |
6201 } | 6145 } |
6202 | 6146 |
6203 bool NeedsWriteBarrierForMap() { | 6147 bool NeedsWriteBarrierForMap() { |
6204 if (IsSkipWriteBarrier()) return false; | 6148 if (IsSkipWriteBarrier()) return false; |
6205 return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); | 6149 return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); |
6206 } | 6150 } |
6207 | 6151 |
6208 virtual void FinalizeUniqueValueId() { | 6152 virtual void FinalizeUniqueValueId() { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6269 new_space_dominator_(NULL) { | 6213 new_space_dominator_(NULL) { |
6270 SetOperandAt(0, obj); | 6214 SetOperandAt(0, obj); |
6271 SetOperandAt(1, key); | 6215 SetOperandAt(1, key); |
6272 SetOperandAt(2, val); | 6216 SetOperandAt(2, val); |
6273 | 6217 |
6274 if (IsFastObjectElementsKind(elements_kind)) { | 6218 if (IsFastObjectElementsKind(elements_kind)) { |
6275 SetFlag(kTrackSideEffectDominators); | 6219 SetFlag(kTrackSideEffectDominators); |
6276 SetGVNFlag(kDependsOnNewSpacePromotion); | 6220 SetGVNFlag(kDependsOnNewSpacePromotion); |
6277 } | 6221 } |
6278 if (is_external()) { | 6222 if (is_external()) { |
6279 SetGVNFlag(kChangesExternalMemory); | 6223 SetGVNFlag(kChangesSpecializedArrayElements); |
6280 SetFlag(kAllowUndefinedAsNaN); | 6224 SetFlag(kAllowUndefinedAsNaN); |
6281 } else if (IsFastDoubleElementsKind(elements_kind)) { | 6225 } else if (IsFastDoubleElementsKind(elements_kind)) { |
6282 SetGVNFlag(kChangesDoubleArrayElements); | 6226 SetGVNFlag(kChangesDoubleArrayElements); |
6283 } else if (IsFastSmiElementsKind(elements_kind)) { | 6227 } else if (IsFastSmiElementsKind(elements_kind)) { |
6284 SetGVNFlag(kChangesArrayElements); | 6228 SetGVNFlag(kChangesArrayElements); |
6285 } else { | 6229 } else { |
6286 SetGVNFlag(kChangesArrayElements); | 6230 SetGVNFlag(kChangesArrayElements); |
6287 } | 6231 } |
6288 | 6232 |
6289 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating. | 6233 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating. |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6520 | 6464 |
6521 private: | 6465 private: |
6522 HStringAdd(HValue* context, HValue* left, HValue* right, StringAddFlags flags) | 6466 HStringAdd(HValue* context, HValue* left, HValue* right, StringAddFlags flags) |
6523 : HBinaryOperation(context, left, right), flags_(flags) { | 6467 : HBinaryOperation(context, left, right), flags_(flags) { |
6524 set_representation(Representation::Tagged()); | 6468 set_representation(Representation::Tagged()); |
6525 SetFlag(kUseGVN); | 6469 SetFlag(kUseGVN); |
6526 SetGVNFlag(kDependsOnMaps); | 6470 SetGVNFlag(kDependsOnMaps); |
6527 SetGVNFlag(kChangesNewSpacePromotion); | 6471 SetGVNFlag(kChangesNewSpacePromotion); |
6528 } | 6472 } |
6529 | 6473 |
6530 // No side-effects except possible allocation. | 6474 // TODO(svenpanne) Might be safe, but leave it out until we know for sure. |
6531 // NOTE: this instruction _does not_ call ToString() on its inputs. | 6475 // virtual bool IsDeletable() const { return true; } |
6532 virtual bool IsDeletable() const { return true; } | |
6533 | 6476 |
6534 const StringAddFlags flags_; | 6477 const StringAddFlags flags_; |
6535 }; | 6478 }; |
6536 | 6479 |
6537 | 6480 |
6538 class HStringCharCodeAt: public HTemplateInstruction<3> { | 6481 class HStringCharCodeAt: public HTemplateInstruction<3> { |
6539 public: | 6482 public: |
6540 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) { | 6483 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) { |
6541 SetOperandAt(0, context); | 6484 SetOperandAt(0, context); |
6542 SetOperandAt(1, string); | 6485 SetOperandAt(1, string); |
6543 SetOperandAt(2, index); | 6486 SetOperandAt(2, index); |
6544 set_representation(Representation::Integer32()); | 6487 set_representation(Representation::Integer32()); |
6545 SetFlag(kUseGVN); | 6488 SetFlag(kUseGVN); |
6546 SetGVNFlag(kDependsOnMaps); | 6489 SetGVNFlag(kDependsOnMaps); |
6547 SetGVNFlag(kChangesNewSpacePromotion); | 6490 SetGVNFlag(kChangesNewSpacePromotion); |
6548 } | 6491 } |
6549 | 6492 |
6550 virtual Representation RequiredInputRepresentation(int index) { | 6493 virtual Representation RequiredInputRepresentation(int index) { |
6551 // The index is supposed to be Integer32. | 6494 // The index is supposed to be Integer32. |
6552 return index == 2 | 6495 return index == 2 |
6553 ? Representation::Integer32() | 6496 ? Representation::Integer32() |
6554 : Representation::Tagged(); | 6497 : Representation::Tagged(); |
6555 } | 6498 } |
6556 | 6499 |
6557 HValue* context() const { return OperandAt(0); } | 6500 HValue* context() { return OperandAt(0); } |
6558 HValue* string() const { return OperandAt(1); } | 6501 HValue* string() { return OperandAt(1); } |
6559 HValue* index() const { return OperandAt(2); } | 6502 HValue* index() { return OperandAt(2); } |
6560 | 6503 |
6561 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt) | 6504 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt) |
6562 | 6505 |
6563 protected: | 6506 protected: |
6564 virtual bool DataEquals(HValue* other) { return true; } | 6507 virtual bool DataEquals(HValue* other) { return true; } |
6565 | 6508 |
6566 virtual Range* InferRange(Zone* zone) { | 6509 virtual Range* InferRange(Zone* zone) { |
6567 return new(zone) Range(0, String::kMaxUtf16CodeUnit); | 6510 return new(zone) Range(0, String::kMaxUtf16CodeUnit); |
6568 } | 6511 } |
6569 | 6512 |
6570 private: | 6513 // TODO(svenpanne) Might be safe, but leave it out until we know for sure. |
6571 // No side effects: runtime function assumes string + number inputs. | 6514 // private: |
6572 virtual bool IsDeletable() const { return true; } | 6515 // virtual bool IsDeletable() const { return true; } |
6573 }; | 6516 }; |
6574 | 6517 |
6575 | 6518 |
6576 class HStringCharFromCode: public HTemplateInstruction<2> { | 6519 class HStringCharFromCode: public HTemplateInstruction<2> { |
6577 public: | 6520 public: |
6578 static HInstruction* New(Zone* zone, | 6521 static HInstruction* New(Zone* zone, |
6579 HValue* context, | 6522 HValue* context, |
6580 HValue* char_code); | 6523 HValue* char_code); |
6581 | 6524 |
6582 virtual Representation RequiredInputRepresentation(int index) { | 6525 virtual Representation RequiredInputRepresentation(int index) { |
6583 return index == 0 | 6526 return index == 0 |
6584 ? Representation::Tagged() | 6527 ? Representation::Tagged() |
6585 : Representation::Integer32(); | 6528 : Representation::Integer32(); |
6586 } | 6529 } |
6587 virtual HType CalculateInferredType() { return HType::String(); } | 6530 virtual HType CalculateInferredType(); |
6588 | 6531 |
6589 HValue* context() const { return OperandAt(0); } | 6532 HValue* context() { return OperandAt(0); } |
6590 HValue* value() const { return OperandAt(1); } | 6533 HValue* value() { return OperandAt(1); } |
6591 | 6534 |
6592 virtual bool DataEquals(HValue* other) { return true; } | 6535 virtual bool DataEquals(HValue* other) { return true; } |
6593 | 6536 |
6594 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode) | 6537 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode) |
6595 | 6538 |
6596 private: | 6539 private: |
6597 HStringCharFromCode(HValue* context, HValue* char_code) { | 6540 HStringCharFromCode(HValue* context, HValue* char_code) { |
6598 SetOperandAt(0, context); | 6541 SetOperandAt(0, context); |
6599 SetOperandAt(1, char_code); | 6542 SetOperandAt(1, char_code); |
6600 set_representation(Representation::Tagged()); | 6543 set_representation(Representation::Tagged()); |
6601 SetFlag(kUseGVN); | 6544 SetFlag(kUseGVN); |
6602 SetGVNFlag(kChangesNewSpacePromotion); | 6545 SetGVNFlag(kChangesNewSpacePromotion); |
6603 } | 6546 } |
6604 | 6547 |
6605 virtual bool IsDeletable() const { | 6548 // TODO(svenpanne) Might be safe, but leave it out until we know for sure. |
6606 return !value()->ToNumberCanBeObserved(); | 6549 // virtual bool IsDeletable() const { return true; } |
6607 } | |
6608 }; | 6550 }; |
6609 | 6551 |
6610 | 6552 |
6611 class HStringLength: public HUnaryOperation { | 6553 class HStringLength: public HUnaryOperation { |
6612 public: | 6554 public: |
6613 static HInstruction* New(Zone* zone, HValue* string); | 6555 static HInstruction* New(Zone* zone, HValue* string); |
6614 | 6556 |
6615 virtual Representation RequiredInputRepresentation(int index) { | 6557 virtual Representation RequiredInputRepresentation(int index) { |
6616 return Representation::Tagged(); | 6558 return Representation::Tagged(); |
6617 } | 6559 } |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7006 virtual bool IsDeletable() const { return true; } | 6948 virtual bool IsDeletable() const { return true; } |
7007 }; | 6949 }; |
7008 | 6950 |
7009 | 6951 |
7010 #undef DECLARE_INSTRUCTION | 6952 #undef DECLARE_INSTRUCTION |
7011 #undef DECLARE_CONCRETE_INSTRUCTION | 6953 #undef DECLARE_CONCRETE_INSTRUCTION |
7012 | 6954 |
7013 } } // namespace v8::internal | 6955 } } // namespace v8::internal |
7014 | 6956 |
7015 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 6957 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |