| 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 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 | 383 |
| 384 HUseListNode* HUseListNode::tail() { | 384 HUseListNode* HUseListNode::tail() { |
| 385 // Skip and remove dead items in the use list. | 385 // Skip and remove dead items in the use list. |
| 386 while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) { | 386 while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) { |
| 387 tail_ = tail_->tail_; | 387 tail_ = tail_->tail_; |
| 388 } | 388 } |
| 389 return tail_; | 389 return tail_; |
| 390 } | 390 } |
| 391 | 391 |
| 392 | 392 |
| 393 bool HValue::CheckUsesForFlag(Flag f) { | 393 bool HValue::CheckUsesForFlag(Flag f) const { |
| 394 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 394 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| 395 if (it.value()->IsSimulate()) continue; | 395 if (it.value()->IsSimulate()) continue; |
| 396 if (!it.value()->CheckFlag(f)) return false; | 396 if (!it.value()->CheckFlag(f)) return false; |
| 397 } | 397 } |
| 398 return true; | 398 return true; |
| 399 } | 399 } |
| 400 | 400 |
| 401 | 401 |
| 402 bool HValue::HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) { | 402 bool HValue::HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const { |
| 403 bool return_value = false; | 403 bool return_value = false; |
| 404 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 404 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| 405 if (it.value()->IsSimulate()) continue; | 405 if (it.value()->IsSimulate()) continue; |
| 406 if (!it.value()->CheckFlag(f)) return false; | 406 if (!it.value()->CheckFlag(f)) return false; |
| 407 return_value = true; | 407 return_value = true; |
| 408 } | 408 } |
| 409 return return_value; | 409 return return_value; |
| 410 } | 410 } |
| 411 | 411 |
| 412 | 412 |
| (...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1280 // A change from an integer32 can be replaced by the integer32 value. | 1280 // A change from an integer32 can be replaced by the integer32 value. |
| 1281 if (dividend->IsChange() && | 1281 if (dividend->IsChange() && |
| 1282 HChange::cast(dividend)->from().IsInteger32()) { | 1282 HChange::cast(dividend)->from().IsInteger32()) { |
| 1283 return HChange::cast(dividend)->value(); | 1283 return HChange::cast(dividend)->value(); |
| 1284 } | 1284 } |
| 1285 return NULL; | 1285 return NULL; |
| 1286 } | 1286 } |
| 1287 | 1287 |
| 1288 | 1288 |
| 1289 HValue* HUnaryMathOperation::Canonicalize() { | 1289 HValue* HUnaryMathOperation::Canonicalize() { |
| 1290 if (op() == kMathRound || op() == kMathFloor) { |
| 1291 HValue* val = value(); |
| 1292 if (val->IsChange()) val = HChange::cast(val)->value(); |
| 1293 |
| 1294 // If the input is smi or integer32 then we replace the instruction with its |
| 1295 // input. |
| 1296 if (val->representation().IsSmiOrInteger32()) { |
| 1297 if (!val->representation().Equals(representation())) { |
| 1298 HChange* result = new(block()->zone()) HChange( |
| 1299 val, representation(), false, false); |
| 1300 result->InsertBefore(this); |
| 1301 return result; |
| 1302 } |
| 1303 return val; |
| 1304 } |
| 1305 } |
| 1306 |
| 1290 if (op() == kMathFloor) { | 1307 if (op() == kMathFloor) { |
| 1291 HValue* val = value(); | 1308 HValue* val = value(); |
| 1292 if (val->IsChange()) val = HChange::cast(val)->value(); | 1309 if (val->IsChange()) val = HChange::cast(val)->value(); |
| 1293 | 1310 if (val->IsDiv() && (val->UseCount() == 1)) { |
| 1294 // If the input is integer32 then we replace the floor instruction | 1311 HDiv* hdiv = HDiv::cast(val); |
| 1295 // with its input. | |
| 1296 if (val->representation().IsSmiOrInteger32()) return val; | |
| 1297 | |
| 1298 #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_IA32) || \ | |
| 1299 defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_A64) | |
| 1300 if (value()->IsDiv() && (value()->UseCount() == 1)) { | |
| 1301 // TODO(2038): Implement this optimization for non ARM architectures. | |
| 1302 HDiv* hdiv = HDiv::cast(value()); | |
| 1303 HValue* left = hdiv->left(); | 1312 HValue* left = hdiv->left(); |
| 1304 HValue* right = hdiv->right(); | 1313 HValue* right = hdiv->right(); |
| 1305 // Try to simplify left and right values of the division. | 1314 // Try to simplify left and right values of the division. |
| 1306 HValue* new_left = SimplifiedDividendForMathFloorOfDiv(left); | 1315 HValue* new_left = SimplifiedDividendForMathFloorOfDiv(left); |
| 1307 if (new_left == NULL && | 1316 if (new_left == NULL && |
| 1308 hdiv->observed_input_representation(1).IsSmiOrInteger32()) { | 1317 hdiv->observed_input_representation(1).IsSmiOrInteger32()) { |
| 1309 new_left = new(block()->zone()) HChange( | 1318 new_left = new(block()->zone()) HChange( |
| 1310 left, Representation::Integer32(), false, false, false); | 1319 left, Representation::Integer32(), false, false); |
| 1311 HChange::cast(new_left)->InsertBefore(this); | 1320 HChange::cast(new_left)->InsertBefore(this); |
| 1312 } | 1321 } |
| 1313 HValue* new_right = | 1322 HValue* new_right = |
| 1314 LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(right); | 1323 LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(right); |
| 1315 if (new_right == NULL && | 1324 if (new_right == NULL && |
| 1316 #if V8_TARGET_ARCH_ARM | 1325 #if V8_TARGET_ARCH_ARM |
| 1317 CpuFeatures::IsSupported(SUDIV) && | 1326 CpuFeatures::IsSupported(SUDIV) && |
| 1318 #endif | 1327 #endif |
| 1319 hdiv->observed_input_representation(2).IsSmiOrInteger32()) { | 1328 hdiv->observed_input_representation(2).IsSmiOrInteger32()) { |
| 1320 new_right = new(block()->zone()) HChange( | 1329 new_right = new(block()->zone()) HChange( |
| 1321 right, Representation::Integer32(), false, false, false); | 1330 right, Representation::Integer32(), false, false); |
| 1322 HChange::cast(new_right)->InsertBefore(this); | 1331 HChange::cast(new_right)->InsertBefore(this); |
| 1323 } | 1332 } |
| 1324 | 1333 |
| 1325 // Return if left or right are not optimizable. | 1334 // Return if left or right are not optimizable. |
| 1326 if ((new_left == NULL) || (new_right == NULL)) return this; | 1335 if ((new_left == NULL) || (new_right == NULL)) return this; |
| 1327 | 1336 |
| 1328 // Insert the new values in the graph. | 1337 // Insert the new values in the graph. |
| 1329 if (new_left->IsInstruction() && | 1338 if (new_left->IsInstruction() && |
| 1330 !HInstruction::cast(new_left)->IsLinked()) { | 1339 !HInstruction::cast(new_left)->IsLinked()) { |
| 1331 HInstruction::cast(new_left)->InsertBefore(this); | 1340 HInstruction::cast(new_left)->InsertBefore(this); |
| 1332 } | 1341 } |
| 1333 if (new_right->IsInstruction() && | 1342 if (new_right->IsInstruction() && |
| 1334 !HInstruction::cast(new_right)->IsLinked()) { | 1343 !HInstruction::cast(new_right)->IsLinked()) { |
| 1335 HInstruction::cast(new_right)->InsertBefore(this); | 1344 HInstruction::cast(new_right)->InsertBefore(this); |
| 1336 } | 1345 } |
| 1337 HMathFloorOfDiv* instr = | 1346 HMathFloorOfDiv* instr = |
| 1338 HMathFloorOfDiv::New(block()->zone(), context(), new_left, new_right); | 1347 HMathFloorOfDiv::New(block()->zone(), context(), new_left, new_right); |
| 1339 // Replace this HMathFloor instruction by the new HMathFloorOfDiv. | 1348 // Replace this HMathFloor instruction by the new HMathFloorOfDiv. |
| 1340 instr->InsertBefore(this); | 1349 instr->InsertBefore(this); |
| 1341 ReplaceAllUsesWith(instr); | 1350 ReplaceAllUsesWith(instr); |
| 1342 Kill(); | 1351 Kill(); |
| 1343 // We know the division had no other uses than this HMathFloor. Delete it. | 1352 // We know the division had no other uses than this HMathFloor. Delete it. |
| 1344 // Dead code elimination will deal with |left| and |right| if | 1353 // Dead code elimination will deal with |left| and |right| if |
| 1345 // appropriate. | 1354 // appropriate. |
| 1346 hdiv->DeleteAndReplaceWith(NULL); | 1355 hdiv->DeleteAndReplaceWith(NULL); |
| 1347 | 1356 |
| 1348 // Return NULL to remove this instruction from the graph. | 1357 // Return NULL to remove this instruction from the graph. |
| 1349 return NULL; | 1358 return NULL; |
| 1350 } | 1359 } |
| 1351 #endif | |
| 1352 } | 1360 } |
| 1353 return this; | 1361 return this; |
| 1354 } | 1362 } |
| 1355 | 1363 |
| 1356 | 1364 |
| 1357 HValue* HCheckInstanceType::Canonicalize() { | 1365 HValue* HCheckInstanceType::Canonicalize() { |
| 1358 if (check_ == IS_STRING && value()->type().IsString()) { | 1366 if (check_ == IS_STRING && value()->type().IsString()) { |
| 1359 return value(); | 1367 return value(); |
| 1360 } | 1368 } |
| 1361 | 1369 |
| (...skipping 1410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2772 | 2780 |
| 2773 | 2781 |
| 2774 void HCompareObjectEqAndBranch::PrintDataTo(StringStream* stream) { | 2782 void HCompareObjectEqAndBranch::PrintDataTo(StringStream* stream) { |
| 2775 left()->PrintNameTo(stream); | 2783 left()->PrintNameTo(stream); |
| 2776 stream->Add(" "); | 2784 stream->Add(" "); |
| 2777 right()->PrintNameTo(stream); | 2785 right()->PrintNameTo(stream); |
| 2778 HControlInstruction::PrintDataTo(stream); | 2786 HControlInstruction::PrintDataTo(stream); |
| 2779 } | 2787 } |
| 2780 | 2788 |
| 2781 | 2789 |
| 2790 void HCompareHoleAndBranch::PrintDataTo(StringStream* stream) { |
| 2791 object()->PrintNameTo(stream); |
| 2792 HControlInstruction::PrintDataTo(stream); |
| 2793 } |
| 2794 |
| 2795 |
| 2796 void HCompareHoleAndBranch::InferRepresentation( |
| 2797 HInferRepresentationPhase* h_infer) { |
| 2798 ChangeRepresentation(object()->representation()); |
| 2799 } |
| 2800 |
| 2801 |
| 2782 void HGoto::PrintDataTo(StringStream* stream) { | 2802 void HGoto::PrintDataTo(StringStream* stream) { |
| 2783 stream->Add("B%d", SuccessorAt(0)->block_id()); | 2803 stream->Add("B%d", SuccessorAt(0)->block_id()); |
| 2784 } | 2804 } |
| 2785 | 2805 |
| 2786 | 2806 |
| 2787 void HCompareNumericAndBranch::InferRepresentation( | 2807 void HCompareNumericAndBranch::InferRepresentation( |
| 2788 HInferRepresentationPhase* h_infer) { | 2808 HInferRepresentationPhase* h_infer) { |
| 2789 Representation left_rep = left()->representation(); | 2809 Representation left_rep = left()->representation(); |
| 2790 Representation right_rep = right()->representation(); | 2810 Representation right_rep = right()->representation(); |
| 2791 Representation observed_left = observed_input_representation(0); | 2811 Representation observed_left = observed_input_representation(0); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2831 void HLoadNamedField::PrintDataTo(StringStream* stream) { | 2851 void HLoadNamedField::PrintDataTo(StringStream* stream) { |
| 2832 object()->PrintNameTo(stream); | 2852 object()->PrintNameTo(stream); |
| 2833 access_.PrintTo(stream); | 2853 access_.PrintTo(stream); |
| 2834 if (HasTypeCheck()) { | 2854 if (HasTypeCheck()) { |
| 2835 stream->Add(" "); | 2855 stream->Add(" "); |
| 2836 typecheck()->PrintNameTo(stream); | 2856 typecheck()->PrintNameTo(stream); |
| 2837 } | 2857 } |
| 2838 } | 2858 } |
| 2839 | 2859 |
| 2840 | 2860 |
| 2841 // Returns true if an instance of this map can never find a property with this | |
| 2842 // name in its prototype chain. This means all prototypes up to the top are | |
| 2843 // fast and don't have the name in them. It would be good if we could optimize | |
| 2844 // polymorphic loads where the property is sometimes found in the prototype | |
| 2845 // chain. | |
| 2846 static bool PrototypeChainCanNeverResolve( | |
| 2847 Handle<Map> map, Handle<String> name) { | |
| 2848 Isolate* isolate = map->GetIsolate(); | |
| 2849 Object* current = map->prototype(); | |
| 2850 while (current != isolate->heap()->null_value()) { | |
| 2851 if (current->IsJSGlobalProxy() || | |
| 2852 current->IsGlobalObject() || | |
| 2853 !current->IsJSObject() || | |
| 2854 JSObject::cast(current)->map()->has_named_interceptor() || | |
| 2855 JSObject::cast(current)->IsAccessCheckNeeded() || | |
| 2856 !JSObject::cast(current)->HasFastProperties()) { | |
| 2857 return false; | |
| 2858 } | |
| 2859 | |
| 2860 LookupResult lookup(isolate); | |
| 2861 Map* map = JSObject::cast(current)->map(); | |
| 2862 map->LookupDescriptor(NULL, *name, &lookup); | |
| 2863 if (lookup.IsFound()) return false; | |
| 2864 if (!lookup.IsCacheable()) return false; | |
| 2865 current = JSObject::cast(current)->GetPrototype(); | |
| 2866 } | |
| 2867 return true; | |
| 2868 } | |
| 2869 | |
| 2870 | |
| 2871 HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context, | |
| 2872 HValue* object, | |
| 2873 SmallMapList* types, | |
| 2874 Handle<String> name, | |
| 2875 Zone* zone) | |
| 2876 : types_(Min(types->length(), kMaxLoadPolymorphism), zone), | |
| 2877 name_(name), | |
| 2878 types_unique_ids_(0, zone), | |
| 2879 name_unique_id_(), | |
| 2880 need_generic_(false) { | |
| 2881 SetOperandAt(0, context); | |
| 2882 SetOperandAt(1, object); | |
| 2883 set_representation(Representation::Tagged()); | |
| 2884 SetGVNFlag(kDependsOnMaps); | |
| 2885 SmallMapList negative_lookups; | |
| 2886 for (int i = 0; | |
| 2887 i < types->length() && types_.length() < kMaxLoadPolymorphism; | |
| 2888 ++i) { | |
| 2889 Handle<Map> map = types->at(i); | |
| 2890 // Deprecated maps are updated to the current map in the type oracle. | |
| 2891 ASSERT(!map->is_deprecated()); | |
| 2892 LookupResult lookup(map->GetIsolate()); | |
| 2893 map->LookupDescriptor(NULL, *name, &lookup); | |
| 2894 if (lookup.IsFound()) { | |
| 2895 switch (lookup.type()) { | |
| 2896 case FIELD: { | |
| 2897 int index = lookup.GetLocalFieldIndexFromMap(*map); | |
| 2898 if (index < 0) { | |
| 2899 SetGVNFlag(kDependsOnInobjectFields); | |
| 2900 } else { | |
| 2901 SetGVNFlag(kDependsOnBackingStoreFields); | |
| 2902 } | |
| 2903 if (FLAG_track_double_fields && | |
| 2904 lookup.representation().IsDouble()) { | |
| 2905 // Since the value needs to be boxed, use a generic handler for | |
| 2906 // loading doubles. | |
| 2907 continue; | |
| 2908 } | |
| 2909 types_.Add(types->at(i), zone); | |
| 2910 break; | |
| 2911 } | |
| 2912 case CONSTANT: | |
| 2913 types_.Add(types->at(i), zone); | |
| 2914 break; | |
| 2915 case CALLBACKS: | |
| 2916 break; | |
| 2917 case TRANSITION: | |
| 2918 case INTERCEPTOR: | |
| 2919 case NONEXISTENT: | |
| 2920 case NORMAL: | |
| 2921 case HANDLER: | |
| 2922 UNREACHABLE(); | |
| 2923 break; | |
| 2924 } | |
| 2925 } else if (lookup.IsCacheable() && | |
| 2926 // For dicts the lookup on the map will fail, but the object may | |
| 2927 // contain the property so we cannot generate a negative lookup | |
| 2928 // (which would just be a map check and return undefined). | |
| 2929 !map->is_dictionary_map() && | |
| 2930 !map->has_named_interceptor() && | |
| 2931 PrototypeChainCanNeverResolve(map, name)) { | |
| 2932 negative_lookups.Add(types->at(i), zone); | |
| 2933 } | |
| 2934 } | |
| 2935 | |
| 2936 bool need_generic = | |
| 2937 (types->length() != negative_lookups.length() + types_.length()); | |
| 2938 if (!need_generic && FLAG_deoptimize_uncommon_cases) { | |
| 2939 SetFlag(kUseGVN); | |
| 2940 for (int i = 0; i < negative_lookups.length(); i++) { | |
| 2941 types_.Add(negative_lookups.at(i), zone); | |
| 2942 } | |
| 2943 } else { | |
| 2944 // We don't have an easy way to handle both a call (to the generic stub) and | |
| 2945 // a deopt in the same hydrogen instruction, so in this case we don't add | |
| 2946 // the negative lookups which can deopt - just let the generic stub handle | |
| 2947 // them. | |
| 2948 SetAllSideEffects(); | |
| 2949 need_generic_ = true; | |
| 2950 } | |
| 2951 } | |
| 2952 | |
| 2953 | |
| 2954 HCheckMaps* HCheckMaps::New(Zone* zone, | 2861 HCheckMaps* HCheckMaps::New(Zone* zone, |
| 2955 HValue* context, | 2862 HValue* context, |
| 2956 HValue* value, | 2863 HValue* value, |
| 2957 Handle<Map> map, | 2864 Handle<Map> map, |
| 2958 CompilationInfo* info, | 2865 CompilationInfo* info, |
| 2959 HValue* typecheck) { | 2866 HValue* typecheck) { |
| 2960 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); | 2867 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); |
| 2961 check_map->map_set_.Add(map, zone); | 2868 check_map->Add(map, zone); |
| 2962 check_map->has_migration_target_ = map->is_migration_target(); | |
| 2963 if (map->CanOmitMapChecks() && | 2869 if (map->CanOmitMapChecks() && |
| 2964 value->IsConstant() && | 2870 value->IsConstant() && |
| 2965 HConstant::cast(value)->InstanceOf(map)) { | 2871 HConstant::cast(value)->InstanceOf(map)) { |
| 2966 check_map->omit(info); | 2872 check_map->omit(info); |
| 2967 } | 2873 } |
| 2968 return check_map; | 2874 return check_map; |
| 2969 } | 2875 } |
| 2970 | 2876 |
| 2971 | 2877 |
| 2972 void HCheckMaps::FinalizeUniqueValueId() { | 2878 void HCheckMaps::FinalizeUniqueValueId() { |
| 2973 if (!map_unique_ids_.is_empty()) return; | 2879 if (!map_unique_ids_.is_empty()) return; |
| 2974 Zone* zone = block()->zone(); | 2880 Zone* zone = block()->zone(); |
| 2975 map_unique_ids_.Initialize(map_set_.length(), zone); | 2881 map_unique_ids_.Initialize(map_set_.length(), zone); |
| 2976 for (int i = 0; i < map_set_.length(); i++) { | 2882 for (int i = 0; i < map_set_.length(); i++) { |
| 2977 map_unique_ids_.Add(UniqueValueId(map_set_.at(i)), zone); | 2883 map_unique_ids_.Add(UniqueValueId(map_set_.at(i)), zone); |
| 2978 } | 2884 } |
| 2979 } | 2885 } |
| 2980 | 2886 |
| 2981 | 2887 |
| 2982 void HLoadNamedFieldPolymorphic::FinalizeUniqueValueId() { | |
| 2983 if (!types_unique_ids_.is_empty()) return; | |
| 2984 Zone* zone = block()->zone(); | |
| 2985 types_unique_ids_.Initialize(types_.length(), zone); | |
| 2986 for (int i = 0; i < types_.length(); i++) { | |
| 2987 types_unique_ids_.Add(UniqueValueId(types_.at(i)), zone); | |
| 2988 } | |
| 2989 name_unique_id_ = UniqueValueId(name_); | |
| 2990 } | |
| 2991 | |
| 2992 | |
| 2993 bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) { | |
| 2994 ASSERT_EQ(types_.length(), types_unique_ids_.length()); | |
| 2995 HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value); | |
| 2996 if (name_unique_id_ != other->name_unique_id_) return false; | |
| 2997 if (types_unique_ids_.length() != other->types_unique_ids_.length()) { | |
| 2998 return false; | |
| 2999 } | |
| 3000 if (need_generic_ != other->need_generic_) return false; | |
| 3001 for (int i = 0; i < types_unique_ids_.length(); i++) { | |
| 3002 bool found = false; | |
| 3003 for (int j = 0; j < types_unique_ids_.length(); j++) { | |
| 3004 if (types_unique_ids_.at(j) == other->types_unique_ids_.at(i)) { | |
| 3005 found = true; | |
| 3006 break; | |
| 3007 } | |
| 3008 } | |
| 3009 if (!found) return false; | |
| 3010 } | |
| 3011 return true; | |
| 3012 } | |
| 3013 | |
| 3014 | |
| 3015 void HLoadNamedFieldPolymorphic::PrintDataTo(StringStream* stream) { | |
| 3016 object()->PrintNameTo(stream); | |
| 3017 stream->Add("."); | |
| 3018 stream->Add(*String::cast(*name())->ToCString()); | |
| 3019 } | |
| 3020 | |
| 3021 | |
| 3022 void HLoadNamedGeneric::PrintDataTo(StringStream* stream) { | 2888 void HLoadNamedGeneric::PrintDataTo(StringStream* stream) { |
| 3023 object()->PrintNameTo(stream); | 2889 object()->PrintNameTo(stream); |
| 3024 stream->Add("."); | 2890 stream->Add("."); |
| 3025 stream->Add(*String::cast(*name())->ToCString()); | 2891 stream->Add(*String::cast(*name())->ToCString()); |
| 3026 } | 2892 } |
| 3027 | 2893 |
| 3028 | 2894 |
| 3029 void HLoadKeyed::PrintDataTo(StringStream* stream) { | 2895 void HLoadKeyed::PrintDataTo(StringStream* stream) { |
| 3030 if (!is_external()) { | 2896 if (!is_external()) { |
| 3031 elements()->PrintNameTo(stream); | 2897 elements()->PrintNameTo(stream); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3084 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 2950 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| 3085 HValue* use = it.value(); | 2951 HValue* use = it.value(); |
| 3086 if (!use->IsChange()) return false; | 2952 if (!use->IsChange()) return false; |
| 3087 } | 2953 } |
| 3088 | 2954 |
| 3089 return true; | 2955 return true; |
| 3090 } | 2956 } |
| 3091 | 2957 |
| 3092 | 2958 |
| 3093 bool HLoadKeyed::AllUsesCanTreatHoleAsNaN() const { | 2959 bool HLoadKeyed::AllUsesCanTreatHoleAsNaN() const { |
| 3094 if (!IsFastDoubleElementsKind(elements_kind())) { | 2960 return IsFastDoubleElementsKind(elements_kind()) && |
| 3095 return false; | 2961 CheckUsesForFlag(HValue::kAllowUndefinedAsNaN); |
| 3096 } | |
| 3097 | |
| 3098 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | |
| 3099 HValue* use = it.value(); | |
| 3100 if (!use->CheckFlag(HValue::kAllowUndefinedAsNaN)) { | |
| 3101 return false; | |
| 3102 } | |
| 3103 } | |
| 3104 | |
| 3105 return true; | |
| 3106 } | 2962 } |
| 3107 | 2963 |
| 3108 | 2964 |
| 3109 bool HLoadKeyed::RequiresHoleCheck() const { | 2965 bool HLoadKeyed::RequiresHoleCheck() const { |
| 3110 if (IsFastPackedElementsKind(elements_kind())) { | 2966 if (IsFastPackedElementsKind(elements_kind())) { |
| 3111 return false; | 2967 return false; |
| 3112 } | 2968 } |
| 3113 | 2969 |
| 3114 if (IsExternalArrayElementsKind(elements_kind())) { | 2970 if (IsExternalArrayElementsKind(elements_kind())) { |
| 3115 return false; | 2971 return false; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3224 | 3080 |
| 3225 void HTransitionElementsKind::PrintDataTo(StringStream* stream) { | 3081 void HTransitionElementsKind::PrintDataTo(StringStream* stream) { |
| 3226 object()->PrintNameTo(stream); | 3082 object()->PrintNameTo(stream); |
| 3227 ElementsKind from_kind = original_map()->elements_kind(); | 3083 ElementsKind from_kind = original_map()->elements_kind(); |
| 3228 ElementsKind to_kind = transitioned_map()->elements_kind(); | 3084 ElementsKind to_kind = transitioned_map()->elements_kind(); |
| 3229 stream->Add(" %p [%s] -> %p [%s]", | 3085 stream->Add(" %p [%s] -> %p [%s]", |
| 3230 *original_map(), | 3086 *original_map(), |
| 3231 ElementsAccessor::ForKind(from_kind)->name(), | 3087 ElementsAccessor::ForKind(from_kind)->name(), |
| 3232 *transitioned_map(), | 3088 *transitioned_map(), |
| 3233 ElementsAccessor::ForKind(to_kind)->name()); | 3089 ElementsAccessor::ForKind(to_kind)->name()); |
| 3090 if (IsSimpleMapChangeTransition(from_kind, to_kind)) stream->Add(" (simple)"); |
| 3234 } | 3091 } |
| 3235 | 3092 |
| 3236 | 3093 |
| 3237 void HLoadGlobalCell::PrintDataTo(StringStream* stream) { | 3094 void HLoadGlobalCell::PrintDataTo(StringStream* stream) { |
| 3238 stream->Add("[%p]", *cell()); | 3095 stream->Add("[%p]", *cell()); |
| 3239 if (!details_.IsDontDelete()) stream->Add(" (deleteable)"); | 3096 if (!details_.IsDontDelete()) stream->Add(" (deleteable)"); |
| 3240 if (details_.IsReadOnly()) stream->Add(" (read-only)"); | 3097 if (details_.IsReadOnly()) stream->Add(" (read-only)"); |
| 3241 } | 3098 } |
| 3242 | 3099 |
| 3243 | 3100 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3312 if (from().IsDouble() && to().IsTagged()) return HType::HeapNumber(); | 3169 if (from().IsDouble() && to().IsTagged()) return HType::HeapNumber(); |
| 3313 return type(); | 3170 return type(); |
| 3314 } | 3171 } |
| 3315 | 3172 |
| 3316 | 3173 |
| 3317 Representation HUnaryMathOperation::RepresentationFromInputs() { | 3174 Representation HUnaryMathOperation::RepresentationFromInputs() { |
| 3318 Representation rep = representation(); | 3175 Representation rep = representation(); |
| 3319 // If any of the actual input representation is more general than what we | 3176 // If any of the actual input representation is more general than what we |
| 3320 // have so far but not Tagged, use that representation instead. | 3177 // have so far but not Tagged, use that representation instead. |
| 3321 Representation input_rep = value()->representation(); | 3178 Representation input_rep = value()->representation(); |
| 3322 if (!input_rep.IsTagged()) rep = rep.generalize(input_rep); | 3179 if (!input_rep.IsTagged()) { |
| 3180 rep = rep.generalize(input_rep); |
| 3181 } |
| 3323 return rep; | 3182 return rep; |
| 3324 } | 3183 } |
| 3325 | 3184 |
| 3326 | 3185 |
| 3327 void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, | 3186 void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, |
| 3328 HValue* dominator) { | 3187 HValue* dominator) { |
| 3329 ASSERT(side_effect == kChangesNewSpacePromotion); | 3188 ASSERT(side_effect == kChangesNewSpacePromotion); |
| 3330 if (!FLAG_use_allocation_folding) return; | 3189 if (!FLAG_use_allocation_folding) return; |
| 3331 | 3190 |
| 3332 // Try to fold allocations together with their dominating allocations. | 3191 // Try to fold allocations together with their dominating allocations. |
| (...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3868 for (int i = 0; i < OperandCount(); ++i) { | 3727 for (int i = 0; i < OperandCount(); ++i) { |
| 3869 HConstant* operand = HConstant::cast(OperandAt(i)); | 3728 HConstant* operand = HConstant::cast(OperandAt(i)); |
| 3870 if (operand->HasInteger32Value()) { | 3729 if (operand->HasInteger32Value()) { |
| 3871 continue; | 3730 continue; |
| 3872 } else if (operand->HasDoubleValue()) { | 3731 } else if (operand->HasDoubleValue()) { |
| 3873 HConstant* integer_input = | 3732 HConstant* integer_input = |
| 3874 HConstant::New(graph->zone(), graph->GetInvalidContext(), | 3733 HConstant::New(graph->zone(), graph->GetInvalidContext(), |
| 3875 DoubleToInt32(operand->DoubleValue())); | 3734 DoubleToInt32(operand->DoubleValue())); |
| 3876 integer_input->InsertAfter(operand); | 3735 integer_input->InsertAfter(operand); |
| 3877 SetOperandAt(i, integer_input); | 3736 SetOperandAt(i, integer_input); |
| 3878 } else if (operand == graph->GetConstantTrue()) { | 3737 } else if (operand->HasBooleanValue()) { |
| 3879 SetOperandAt(i, graph->GetConstant1()); | 3738 SetOperandAt(i, operand->BooleanValue() ? graph->GetConstant1() |
| 3880 } else { | 3739 : graph->GetConstant0()); |
| 3881 // This catches |false|, |undefined|, strings and objects. | 3740 } else if (operand->ImmortalImmovable()) { |
| 3882 SetOperandAt(i, graph->GetConstant0()); | 3741 SetOperandAt(i, graph->GetConstant0()); |
| 3883 } | 3742 } |
| 3884 } | 3743 } |
| 3885 // Overwrite observed input representations because they are likely Tagged. | 3744 // Overwrite observed input representations because they are likely Tagged. |
| 3886 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 3745 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| 3887 HValue* use = it.value(); | 3746 HValue* use = it.value(); |
| 3888 if (use->IsBinaryOperation()) { | 3747 if (use->IsBinaryOperation()) { |
| 3889 HBinaryOperation::cast(use)->set_observed_input_representation( | 3748 HBinaryOperation::cast(use)->set_observed_input_representation( |
| 3890 it.index(), Representation::Smi()); | 3749 it.index(), Representation::Smi()); |
| 3891 } | 3750 } |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4141 break; | 4000 break; |
| 4142 case kExternalMemory: | 4001 case kExternalMemory: |
| 4143 stream->Add("[external-memory]"); | 4002 stream->Add("[external-memory]"); |
| 4144 break; | 4003 break; |
| 4145 } | 4004 } |
| 4146 | 4005 |
| 4147 stream->Add("@%d", offset()); | 4006 stream->Add("@%d", offset()); |
| 4148 } | 4007 } |
| 4149 | 4008 |
| 4150 } } // namespace v8::internal | 4009 } } // namespace v8::internal |
| OLD | NEW |