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 5245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5256 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); | 5256 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); |
5257 if (lookup->IsField()) { | 5257 if (lookup->IsField()) { |
5258 return lookup->GetLocalFieldIndexFromMap(*type); | 5258 return lookup->GetLocalFieldIndexFromMap(*type); |
5259 } else { | 5259 } else { |
5260 Map* transition = lookup->GetTransitionMapFromMap(*type); | 5260 Map* transition = lookup->GetTransitionMapFromMap(*type); |
5261 return transition->PropertyIndexFor(*name) - type->inobject_properties(); | 5261 return transition->PropertyIndexFor(*name) - type->inobject_properties(); |
5262 } | 5262 } |
5263 } | 5263 } |
5264 | 5264 |
5265 | 5265 |
| 5266 void HGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
| 5267 Handle<Map> map) { |
| 5268 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 5269 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
| 5270 } |
| 5271 |
| 5272 |
5266 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, | 5273 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, |
5267 Handle<String> name, | 5274 Handle<String> name, |
5268 HValue* value, | 5275 HValue* value, |
5269 Handle<Map> map, | 5276 Handle<Map> map, |
5270 LookupResult* lookup, | 5277 LookupResult* lookup) { |
5271 bool smi_and_map_check) { | |
5272 ASSERT(lookup->IsFound()); | 5278 ASSERT(lookup->IsFound()); |
5273 if (smi_and_map_check) { | |
5274 AddInstruction(new(zone()) HCheckNonSmi(object)); | |
5275 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | |
5276 } | |
5277 | |
5278 // If the property does not exist yet, we have to check that it wasn't made | 5279 // If the property does not exist yet, we have to check that it wasn't made |
5279 // readonly or turned into a setter by some meanwhile modifications on the | 5280 // readonly or turned into a setter by some meanwhile modifications on the |
5280 // prototype chain. | 5281 // prototype chain. |
5281 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { | 5282 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { |
5282 Object* proto = map->prototype(); | 5283 Object* proto = map->prototype(); |
5283 // First check that the prototype chain isn't affected already. | 5284 // First check that the prototype chain isn't affected already. |
5284 LookupResult proto_result(isolate()); | 5285 LookupResult proto_result(isolate()); |
5285 proto->Lookup(*name, &proto_result); | 5286 proto->Lookup(*name, &proto_result); |
5286 if (proto_result.IsProperty()) { | 5287 if (proto_result.IsProperty()) { |
5287 // If the inherited property could induce readonly-ness, bail out. | 5288 // If the inherited property could induce readonly-ness, bail out. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5336 value, | 5337 value, |
5337 function_strict_mode_flag()); | 5338 function_strict_mode_flag()); |
5338 } | 5339 } |
5339 | 5340 |
5340 | 5341 |
5341 HInstruction* HGraphBuilder::BuildCallSetter(HValue* object, | 5342 HInstruction* HGraphBuilder::BuildCallSetter(HValue* object, |
5342 HValue* value, | 5343 HValue* value, |
5343 Handle<Map> map, | 5344 Handle<Map> map, |
5344 Handle<JSFunction> setter, | 5345 Handle<JSFunction> setter, |
5345 Handle<JSObject> holder) { | 5346 Handle<JSObject> holder) { |
5346 AddCheckConstantFunction(holder, object, map, true); | 5347 AddCheckConstantFunction(holder, object, map); |
5347 AddInstruction(new(zone()) HPushArgument(object)); | 5348 AddInstruction(new(zone()) HPushArgument(object)); |
5348 AddInstruction(new(zone()) HPushArgument(value)); | 5349 AddInstruction(new(zone()) HPushArgument(value)); |
5349 return new(zone()) HCallConstantFunction(setter, 2); | 5350 return new(zone()) HCallConstantFunction(setter, 2); |
5350 } | 5351 } |
5351 | 5352 |
5352 | 5353 |
5353 HInstruction* HGraphBuilder::BuildStoreNamedMonomorphic(HValue* object, | 5354 HInstruction* HGraphBuilder::BuildStoreNamedMonomorphic(HValue* object, |
5354 Handle<String> name, | 5355 Handle<String> name, |
5355 HValue* value, | 5356 HValue* value, |
5356 Handle<Map> map) { | 5357 Handle<Map> map) { |
5357 // Handle a store to a known field. | 5358 // Handle a store to a known field. |
5358 LookupResult lookup(isolate()); | 5359 LookupResult lookup(isolate()); |
5359 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 5360 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
5360 // true = needs smi and map check. | 5361 AddCheckMapsWithTransitions(object, map); |
5361 return BuildStoreNamedField(object, name, value, map, &lookup, true); | 5362 return BuildStoreNamedField(object, name, value, map, &lookup); |
5362 } | 5363 } |
5363 | 5364 |
5364 // No luck, do a generic store. | 5365 // No luck, do a generic store. |
5365 return BuildStoreNamedGeneric(object, name, value); | 5366 return BuildStoreNamedGeneric(object, name, value); |
5366 } | 5367 } |
5367 | 5368 |
5368 | 5369 |
5369 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 5370 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
5370 HValue* object, | 5371 HValue* object, |
5371 SmallMapList* types, | 5372 SmallMapList* types, |
(...skipping 27 matching lines...) Expand all Loading... |
5399 ++count; | 5400 ++count; |
5400 } | 5401 } |
5401 } | 5402 } |
5402 | 5403 |
5403 // Use monomorphic load if property lookup results in the same field index | 5404 // Use monomorphic load if property lookup results in the same field index |
5404 // for all maps. Requires special map check on the set of all handled maps. | 5405 // for all maps. Requires special map check on the set of all handled maps. |
5405 AddInstruction(new(zone()) HCheckNonSmi(object)); | 5406 AddInstruction(new(zone()) HCheckNonSmi(object)); |
5406 HInstruction* instr; | 5407 HInstruction* instr; |
5407 if (count == types->length() && is_monomorphic_field) { | 5408 if (count == types->length() && is_monomorphic_field) { |
5408 AddInstruction(new(zone()) HCheckMaps(object, types, zone())); | 5409 AddInstruction(new(zone()) HCheckMaps(object, types, zone())); |
5409 instr = BuildLoadNamedField(object, map, &lookup, false); | 5410 instr = BuildLoadNamedField(object, map, &lookup); |
5410 } else { | 5411 } else { |
5411 HValue* context = environment()->LookupContext(); | 5412 HValue* context = environment()->LookupContext(); |
5412 instr = new(zone()) HLoadNamedFieldPolymorphic(context, | 5413 instr = new(zone()) HLoadNamedFieldPolymorphic(context, |
5413 object, | 5414 object, |
5414 types, | 5415 types, |
5415 name, | 5416 name, |
5416 zone()); | 5417 zone()); |
5417 } | 5418 } |
5418 | 5419 |
5419 instr->set_position(expr->position()); | 5420 instr->set_position(expr->position()); |
(...skipping 22 matching lines...) Expand all Loading... |
5442 ++count; | 5443 ++count; |
5443 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5444 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
5444 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5445 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
5445 HCompareMap* compare = | 5446 HCompareMap* compare = |
5446 new(zone()) HCompareMap(object, map, if_true, if_false); | 5447 new(zone()) HCompareMap(object, map, if_true, if_false); |
5447 current_block()->Finish(compare); | 5448 current_block()->Finish(compare); |
5448 | 5449 |
5449 set_current_block(if_true); | 5450 set_current_block(if_true); |
5450 HInstruction* instr; | 5451 HInstruction* instr; |
5451 CHECK_ALIVE(instr = | 5452 CHECK_ALIVE(instr = |
5452 BuildStoreNamedField(object, name, value, map, &lookup, false)); | 5453 BuildStoreNamedField(object, name, value, map, &lookup)); |
5453 instr->set_position(expr->position()); | 5454 instr->set_position(expr->position()); |
5454 // Goto will add the HSimulate for the store. | 5455 // Goto will add the HSimulate for the store. |
5455 AddInstruction(instr); | 5456 AddInstruction(instr); |
5456 if (!ast_context()->IsEffect()) Push(value); | 5457 if (!ast_context()->IsEffect()) Push(value); |
5457 current_block()->Goto(join); | 5458 current_block()->Goto(join); |
5458 | 5459 |
5459 set_current_block(if_false); | 5460 set_current_block(if_false); |
5460 } | 5461 } |
5461 } | 5462 } |
5462 | 5463 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5518 bool monomorphic = expr->IsMonomorphic(); | 5519 bool monomorphic = expr->IsMonomorphic(); |
5519 Handle<Map> map; | 5520 Handle<Map> map; |
5520 if (monomorphic) { | 5521 if (monomorphic) { |
5521 map = types->first(); | 5522 map = types->first(); |
5522 if (map->is_dictionary_map()) monomorphic = false; | 5523 if (map->is_dictionary_map()) monomorphic = false; |
5523 } | 5524 } |
5524 if (monomorphic) { | 5525 if (monomorphic) { |
5525 Handle<JSFunction> setter; | 5526 Handle<JSFunction> setter; |
5526 Handle<JSObject> holder; | 5527 Handle<JSObject> holder; |
5527 if (LookupSetter(map, name, &setter, &holder)) { | 5528 if (LookupSetter(map, name, &setter, &holder)) { |
5528 AddCheckConstantFunction(holder, object, map, true); | 5529 AddCheckConstantFunction(holder, object, map); |
5529 if (FLAG_inline_accessors && TryInlineSetter(setter, expr, value)) { | 5530 if (FLAG_inline_accessors && TryInlineSetter(setter, expr, value)) { |
5530 return; | 5531 return; |
5531 } | 5532 } |
5532 Drop(2); | 5533 Drop(2); |
5533 AddInstruction(new(zone()) HPushArgument(object)); | 5534 AddInstruction(new(zone()) HPushArgument(object)); |
5534 AddInstruction(new(zone()) HPushArgument(value)); | 5535 AddInstruction(new(zone()) HPushArgument(value)); |
5535 instr = new(zone()) HCallConstantFunction(setter, 2); | 5536 instr = new(zone()) HCallConstantFunction(setter, 2); |
5536 } else { | 5537 } else { |
5537 Drop(2); | 5538 Drop(2); |
5538 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | 5539 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5942 instr->set_position(expr->position()); | 5943 instr->set_position(expr->position()); |
5943 AddInstruction(instr); | 5944 AddInstruction(instr); |
5944 AddSimulate(expr->id()); | 5945 AddSimulate(expr->id()); |
5945 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5946 current_block()->FinishExit(new(zone()) HAbnormalExit); |
5946 set_current_block(NULL); | 5947 set_current_block(NULL); |
5947 } | 5948 } |
5948 | 5949 |
5949 | 5950 |
5950 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 5951 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
5951 Handle<Map> map, | 5952 Handle<Map> map, |
5952 LookupResult* lookup, | 5953 LookupResult* lookup) { |
5953 bool smi_and_map_check) { | |
5954 if (smi_and_map_check) { | |
5955 AddInstruction(new(zone()) HCheckNonSmi(object)); | |
5956 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | |
5957 } | |
5958 | |
5959 int index = lookup->GetLocalFieldIndexFromMap(*map); | 5954 int index = lookup->GetLocalFieldIndexFromMap(*map); |
5960 if (index < 0) { | 5955 if (index < 0) { |
5961 // Negative property indices are in-object properties, indexed | 5956 // Negative property indices are in-object properties, indexed |
5962 // from the end of the fixed part of the object. | 5957 // from the end of the fixed part of the object. |
5963 int offset = (index * kPointerSize) + map->instance_size(); | 5958 int offset = (index * kPointerSize) + map->instance_size(); |
5964 return new(zone()) HLoadNamedField(object, true, offset); | 5959 return new(zone()) HLoadNamedField(object, true, offset); |
5965 } else { | 5960 } else { |
5966 // Non-negative property indices are in the properties array. | 5961 // Non-negative property indices are in the properties array. |
5967 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 5962 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
5968 return new(zone()) HLoadNamedField(object, false, offset); | 5963 return new(zone()) HLoadNamedField(object, false, offset); |
(...skipping 10 matching lines...) Expand all Loading... |
5979 } | 5974 } |
5980 HValue* context = environment()->LookupContext(); | 5975 HValue* context = environment()->LookupContext(); |
5981 return new(zone()) HLoadNamedGeneric(context, object, name); | 5976 return new(zone()) HLoadNamedGeneric(context, object, name); |
5982 } | 5977 } |
5983 | 5978 |
5984 | 5979 |
5985 HInstruction* HGraphBuilder::BuildCallGetter(HValue* object, | 5980 HInstruction* HGraphBuilder::BuildCallGetter(HValue* object, |
5986 Handle<Map> map, | 5981 Handle<Map> map, |
5987 Handle<JSFunction> getter, | 5982 Handle<JSFunction> getter, |
5988 Handle<JSObject> holder) { | 5983 Handle<JSObject> holder) { |
5989 AddCheckConstantFunction(holder, object, map, true); | 5984 AddCheckConstantFunction(holder, object, map); |
5990 AddInstruction(new(zone()) HPushArgument(object)); | 5985 AddInstruction(new(zone()) HPushArgument(object)); |
5991 return new(zone()) HCallConstantFunction(getter, 1); | 5986 return new(zone()) HCallConstantFunction(getter, 1); |
5992 } | 5987 } |
5993 | 5988 |
5994 | 5989 |
5995 HInstruction* HGraphBuilder::BuildLoadNamedMonomorphic(HValue* object, | 5990 HInstruction* HGraphBuilder::BuildLoadNamedMonomorphic(HValue* object, |
5996 Handle<String> name, | 5991 Handle<String> name, |
5997 Property* expr, | 5992 Property* expr, |
5998 Handle<Map> map) { | 5993 Handle<Map> map) { |
5999 // Handle a load from a known field. | 5994 // Handle a load from a known field. |
6000 ASSERT(!map->is_dictionary_map()); | 5995 ASSERT(!map->is_dictionary_map()); |
6001 LookupResult lookup(isolate()); | 5996 LookupResult lookup(isolate()); |
6002 map->LookupDescriptor(NULL, *name, &lookup); | 5997 map->LookupDescriptor(NULL, *name, &lookup); |
6003 if (lookup.IsField()) { | 5998 if (lookup.IsField()) { |
6004 return BuildLoadNamedField(object, map, &lookup, true); | 5999 AddCheckMapsWithTransitions(object, map); |
| 6000 return BuildLoadNamedField(object, map, &lookup); |
6005 } | 6001 } |
6006 | 6002 |
6007 // Handle a load of a constant known function. | 6003 // Handle a load of a constant known function. |
6008 if (lookup.IsConstantFunction()) { | 6004 if (lookup.IsConstantFunction()) { |
6009 AddInstruction(new(zone()) HCheckNonSmi(object)); | 6005 AddCheckMapsWithTransitions(object, map); |
6010 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | |
6011 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 6006 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
6012 return new(zone()) HConstant(function, Representation::Tagged()); | 6007 return new(zone()) HConstant(function, Representation::Tagged()); |
6013 } | 6008 } |
6014 | 6009 |
6015 // Handle a load from a known field somewhere in the protoype chain. | 6010 // Handle a load from a known field somewhere in the protoype chain. |
6016 LookupInPrototypes(map, name, &lookup); | 6011 LookupInPrototypes(map, name, &lookup); |
6017 if (lookup.IsField()) { | 6012 if (lookup.IsField()) { |
6018 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 6013 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
6019 Handle<JSObject> holder(lookup.holder()); | 6014 Handle<JSObject> holder(lookup.holder()); |
6020 Handle<Map> holder_map(holder->map()); | 6015 Handle<Map> holder_map(holder->map()); |
6021 AddInstruction(new(zone()) HCheckNonSmi(object)); | 6016 AddCheckMapsWithTransitions(object, map); |
6022 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | |
6023 HInstruction* holder_value = | 6017 HInstruction* holder_value = |
6024 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder)); | 6018 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder)); |
6025 return BuildLoadNamedField(holder_value, holder_map, &lookup, false); | 6019 return BuildLoadNamedField(holder_value, holder_map, &lookup); |
6026 } | 6020 } |
6027 | 6021 |
6028 // No luck, do a generic load. | 6022 // No luck, do a generic load. |
6029 return BuildLoadNamedGeneric(object, name, expr); | 6023 return BuildLoadNamedGeneric(object, name, expr); |
6030 } | 6024 } |
6031 | 6025 |
6032 | 6026 |
6033 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 6027 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
6034 HValue* key) { | 6028 HValue* key) { |
6035 HValue* context = environment()->LookupContext(); | 6029 HValue* context = environment()->LookupContext(); |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6651 bool monomorphic = expr->IsMonomorphic(); | 6645 bool monomorphic = expr->IsMonomorphic(); |
6652 Handle<Map> map; | 6646 Handle<Map> map; |
6653 if (expr->IsMonomorphic()) { | 6647 if (expr->IsMonomorphic()) { |
6654 map = types->first(); | 6648 map = types->first(); |
6655 if (map->is_dictionary_map()) monomorphic = false; | 6649 if (map->is_dictionary_map()) monomorphic = false; |
6656 } | 6650 } |
6657 if (monomorphic) { | 6651 if (monomorphic) { |
6658 Handle<JSFunction> getter; | 6652 Handle<JSFunction> getter; |
6659 Handle<JSObject> holder; | 6653 Handle<JSObject> holder; |
6660 if (LookupGetter(map, name, &getter, &holder)) { | 6654 if (LookupGetter(map, name, &getter, &holder)) { |
6661 AddCheckConstantFunction(holder, Top(), map, true); | 6655 AddCheckConstantFunction(holder, Top(), map); |
6662 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; | 6656 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; |
6663 AddInstruction(new(zone()) HPushArgument(Pop())); | 6657 AddInstruction(new(zone()) HPushArgument(Pop())); |
6664 instr = new(zone()) HCallConstantFunction(getter, 1); | 6658 instr = new(zone()) HCallConstantFunction(getter, 1); |
6665 } else { | 6659 } else { |
6666 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); | 6660 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); |
6667 } | 6661 } |
6668 } else if (types != NULL && types->length() > 1) { | 6662 } else if (types != NULL && types->length() > 1) { |
6669 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); | 6663 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); |
6670 } else { | 6664 } else { |
6671 instr = BuildLoadNamedGeneric(Pop(), name, expr); | 6665 instr = BuildLoadNamedGeneric(Pop(), name, expr); |
(...skipping 19 matching lines...) Expand all Loading... |
6691 Drop(1); | 6685 Drop(1); |
6692 } | 6686 } |
6693 } | 6687 } |
6694 return ast_context()->ReturnValue(load); | 6688 return ast_context()->ReturnValue(load); |
6695 } | 6689 } |
6696 instr->set_position(expr->position()); | 6690 instr->set_position(expr->position()); |
6697 return ast_context()->ReturnInstruction(instr, expr->id()); | 6691 return ast_context()->ReturnInstruction(instr, expr->id()); |
6698 } | 6692 } |
6699 | 6693 |
6700 | 6694 |
6701 void HGraphBuilder::AddCheckConstantFunction(Handle<JSObject> holder, | 6695 void HGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
6702 HValue* receiver, | 6696 Handle<Map> receiver_map) { |
6703 Handle<Map> receiver_map, | |
6704 bool smi_and_map_check) { | |
6705 // Constant functions have the nice property that the map will change if they | |
6706 // are overwritten. Therefore it is enough to check the map of the holder and | |
6707 // its prototypes. | |
6708 if (smi_and_map_check) { | |
6709 AddInstruction(new(zone()) HCheckNonSmi(receiver)); | |
6710 AddInstruction(HCheckMaps::NewWithTransitions(receiver, receiver_map, | |
6711 zone())); | |
6712 } | |
6713 if (!holder.is_null()) { | 6697 if (!holder.is_null()) { |
6714 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6698 AddInstruction(new(zone()) HCheckPrototypeMaps( |
6715 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); | 6699 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); |
6716 } | 6700 } |
6717 } | 6701 } |
6718 | 6702 |
6719 | 6703 |
| 6704 void HGraphBuilder::AddCheckConstantFunction(Handle<JSObject> holder, |
| 6705 HValue* receiver, |
| 6706 Handle<Map> receiver_map) { |
| 6707 // Constant functions have the nice property that the map will change if they |
| 6708 // are overwritten. Therefore it is enough to check the map of the holder and |
| 6709 // its prototypes. |
| 6710 AddCheckMapsWithTransitions(receiver, receiver_map); |
| 6711 AddCheckPrototypeMaps(holder, receiver_map); |
| 6712 } |
| 6713 |
| 6714 |
6720 class FunctionSorter { | 6715 class FunctionSorter { |
6721 public: | 6716 public: |
6722 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { } | 6717 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { } |
6723 FunctionSorter(int index, int ticks, int ast_length, int src_length) | 6718 FunctionSorter(int index, int ticks, int ast_length, int src_length) |
6724 : index_(index), | 6719 : index_(index), |
6725 ticks_(ticks), | 6720 ticks_(ticks), |
6726 ast_length_(ast_length), | 6721 ast_length_(ast_length), |
6727 src_length_(src_length) { } | 6722 src_length_(src_length) { } |
6728 | 6723 |
6729 int index() const { return index_; } | 6724 int index() const { return index_; } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6788 join = graph()->CreateBasicBlock(); | 6783 join = graph()->CreateBasicBlock(); |
6789 } | 6784 } |
6790 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 6785 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
6791 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 6786 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
6792 HCompareMap* compare = | 6787 HCompareMap* compare = |
6793 new(zone()) HCompareMap(receiver, map, if_true, if_false); | 6788 new(zone()) HCompareMap(receiver, map, if_true, if_false); |
6794 current_block()->Finish(compare); | 6789 current_block()->Finish(compare); |
6795 | 6790 |
6796 set_current_block(if_true); | 6791 set_current_block(if_true); |
6797 expr->ComputeTarget(map, name); | 6792 expr->ComputeTarget(map, name); |
6798 AddCheckConstantFunction(expr->holder(), receiver, map, false); | 6793 AddCheckPrototypeMaps(expr->holder(), map); |
6799 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 6794 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
6800 Handle<JSFunction> caller = info()->closure(); | 6795 Handle<JSFunction> caller = info()->closure(); |
6801 SmartArrayPointer<char> caller_name = | 6796 SmartArrayPointer<char> caller_name = |
6802 caller->shared()->DebugName()->ToCString(); | 6797 caller->shared()->DebugName()->ToCString(); |
6803 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6798 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
6804 *name->ToCString(), | 6799 *name->ToCString(), |
6805 *caller_name); | 6800 *caller_name); |
6806 } | 6801 } |
6807 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 6802 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { |
6808 // Trying to inline will signal that we should bailout from the | 6803 // Trying to inline will signal that we should bailout from the |
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7343 break; | 7338 break; |
7344 case kMathRound: | 7339 case kMathRound: |
7345 case kMathFloor: | 7340 case kMathFloor: |
7346 case kMathAbs: | 7341 case kMathAbs: |
7347 case kMathSqrt: | 7342 case kMathSqrt: |
7348 case kMathLog: | 7343 case kMathLog: |
7349 case kMathSin: | 7344 case kMathSin: |
7350 case kMathCos: | 7345 case kMathCos: |
7351 case kMathTan: | 7346 case kMathTan: |
7352 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { | 7347 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
7353 AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); | 7348 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
7354 HValue* argument = Pop(); | 7349 HValue* argument = Pop(); |
7355 HValue* context = environment()->LookupContext(); | 7350 HValue* context = environment()->LookupContext(); |
7356 Drop(1); // Receiver. | 7351 Drop(1); // Receiver. |
7357 HUnaryMathOperation* op = | 7352 HUnaryMathOperation* op = |
7358 new(zone()) HUnaryMathOperation(context, argument, id); | 7353 new(zone()) HUnaryMathOperation(context, argument, id); |
7359 op->set_position(expr->position()); | 7354 op->set_position(expr->position()); |
7360 ast_context()->ReturnInstruction(op, expr->id()); | 7355 ast_context()->ReturnInstruction(op, expr->id()); |
7361 return true; | 7356 return true; |
7362 } | 7357 } |
7363 break; | 7358 break; |
7364 case kMathPow: | 7359 case kMathPow: |
7365 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 7360 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
7366 AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); | 7361 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
7367 HValue* right = Pop(); | 7362 HValue* right = Pop(); |
7368 HValue* left = Pop(); | 7363 HValue* left = Pop(); |
7369 Pop(); // Pop receiver. | 7364 Pop(); // Pop receiver. |
7370 HValue* context = environment()->LookupContext(); | 7365 HValue* context = environment()->LookupContext(); |
7371 HInstruction* result = NULL; | 7366 HInstruction* result = NULL; |
7372 // Use sqrt() if exponent is 0.5 or -0.5. | 7367 // Use sqrt() if exponent is 0.5 or -0.5. |
7373 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { | 7368 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { |
7374 double exponent = HConstant::cast(right)->DoubleValue(); | 7369 double exponent = HConstant::cast(right)->DoubleValue(); |
7375 if (exponent == 0.5) { | 7370 if (exponent == 0.5) { |
7376 result = | 7371 result = |
(...skipping 21 matching lines...) Expand all Loading... |
7398 | 7393 |
7399 if (result == NULL) { | 7394 if (result == NULL) { |
7400 result = new(zone()) HPower(left, right); | 7395 result = new(zone()) HPower(left, right); |
7401 } | 7396 } |
7402 ast_context()->ReturnInstruction(result, expr->id()); | 7397 ast_context()->ReturnInstruction(result, expr->id()); |
7403 return true; | 7398 return true; |
7404 } | 7399 } |
7405 break; | 7400 break; |
7406 case kMathRandom: | 7401 case kMathRandom: |
7407 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { | 7402 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { |
7408 AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); | 7403 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
7409 Drop(1); // Receiver. | 7404 Drop(1); // Receiver. |
7410 HValue* context = environment()->LookupContext(); | 7405 HValue* context = environment()->LookupContext(); |
7411 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 7406 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
7412 AddInstruction(global_object); | 7407 AddInstruction(global_object); |
7413 HRandom* result = new(zone()) HRandom(global_object); | 7408 HRandom* result = new(zone()) HRandom(global_object); |
7414 ast_context()->ReturnInstruction(result, expr->id()); | 7409 ast_context()->ReturnInstruction(result, expr->id()); |
7415 return true; | 7410 return true; |
7416 } | 7411 } |
7417 break; | 7412 break; |
7418 case kMathMax: | 7413 case kMathMax: |
7419 case kMathMin: | 7414 case kMathMin: |
7420 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 7415 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
7421 AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); | 7416 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
7422 HValue* right = Pop(); | 7417 HValue* right = Pop(); |
7423 HValue* left = Pop(); | 7418 HValue* left = Pop(); |
7424 Drop(1); // Receiver. | 7419 Drop(1); // Receiver. |
7425 HValue* context = environment()->LookupContext(); | 7420 HValue* context = environment()->LookupContext(); |
7426 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin | 7421 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin |
7427 : HMathMinMax::kMathMax; | 7422 : HMathMinMax::kMathMax; |
7428 HMathMinMax* result = new(zone()) HMathMinMax(context, left, right, op); | 7423 HMathMinMax* result = new(zone()) HMathMinMax(context, left, right, op); |
7429 ast_context()->ReturnInstruction(result, expr->id()); | 7424 ast_context()->ReturnInstruction(result, expr->id()); |
7430 return true; | 7425 return true; |
7431 } | 7426 } |
(...skipping 28 matching lines...) Expand all Loading... |
7460 | 7455 |
7461 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 7456 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
7462 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 7457 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
7463 HValue* arg_two_value = environment()->Lookup(arg_two->var()); | 7458 HValue* arg_two_value = environment()->Lookup(arg_two->var()); |
7464 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 7459 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
7465 | 7460 |
7466 // Found pattern f.apply(receiver, arguments). | 7461 // Found pattern f.apply(receiver, arguments). |
7467 VisitForValue(prop->obj()); | 7462 VisitForValue(prop->obj()); |
7468 if (HasStackOverflow() || current_block() == NULL) return true; | 7463 if (HasStackOverflow() || current_block() == NULL) return true; |
7469 HValue* function = Top(); | 7464 HValue* function = Top(); |
7470 AddCheckConstantFunction(expr->holder(), function, function_map, true); | 7465 AddCheckConstantFunction(expr->holder(), function, function_map); |
7471 Drop(1); | 7466 Drop(1); |
7472 | 7467 |
7473 VisitForValue(args->at(0)); | 7468 VisitForValue(args->at(0)); |
7474 if (HasStackOverflow() || current_block() == NULL) return true; | 7469 if (HasStackOverflow() || current_block() == NULL) return true; |
7475 HValue* receiver = Pop(); | 7470 HValue* receiver = Pop(); |
7476 | 7471 |
7477 if (function_state()->outer() == NULL) { | 7472 if (function_state()->outer() == NULL) { |
7478 HInstruction* elements = AddInstruction( | 7473 HInstruction* elements = AddInstruction( |
7479 new(zone()) HArgumentsElements(false)); | 7474 new(zone()) HArgumentsElements(false)); |
7480 HInstruction* length = | 7475 HInstruction* length = |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7579 | 7574 |
7580 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || | 7575 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || |
7581 expr->check_type() != RECEIVER_MAP_CHECK) { | 7576 expr->check_type() != RECEIVER_MAP_CHECK) { |
7582 // When the target has a custom call IC generator, use the IC, | 7577 // When the target has a custom call IC generator, use the IC, |
7583 // because it is likely to generate better code. Also use the IC | 7578 // because it is likely to generate better code. Also use the IC |
7584 // when a primitive receiver check is required. | 7579 // when a primitive receiver check is required. |
7585 HValue* context = environment()->LookupContext(); | 7580 HValue* context = environment()->LookupContext(); |
7586 call = PreProcessCall( | 7581 call = PreProcessCall( |
7587 new(zone()) HCallNamed(context, name, argument_count)); | 7582 new(zone()) HCallNamed(context, name, argument_count)); |
7588 } else { | 7583 } else { |
7589 AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); | 7584 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
7590 | 7585 |
7591 if (TryInlineCall(expr)) return; | 7586 if (TryInlineCall(expr)) return; |
7592 call = PreProcessCall( | 7587 call = PreProcessCall( |
7593 new(zone()) HCallConstantFunction(expr->target(), | 7588 new(zone()) HCallConstantFunction(expr->target(), |
7594 argument_count)); | 7589 argument_count)); |
7595 } | 7590 } |
7596 } else if (types != NULL && types->length() > 1) { | 7591 } else if (types != NULL && types->length() > 1) { |
7597 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 7592 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
7598 HandlePolymorphicCallNamed(expr, receiver, types, name); | 7593 HandlePolymorphicCallNamed(expr, receiver, types, name); |
7599 return; | 7594 return; |
(...skipping 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8653 HIn* result = new(zone()) HIn(context, left, right); | 8648 HIn* result = new(zone()) HIn(context, left, right); |
8654 result->set_position(expr->position()); | 8649 result->set_position(expr->position()); |
8655 return ast_context()->ReturnInstruction(result, expr->id()); | 8650 return ast_context()->ReturnInstruction(result, expr->id()); |
8656 } else if (type_info.IsNonPrimitive()) { | 8651 } else if (type_info.IsNonPrimitive()) { |
8657 switch (op) { | 8652 switch (op) { |
8658 case Token::EQ: | 8653 case Token::EQ: |
8659 case Token::EQ_STRICT: { | 8654 case Token::EQ_STRICT: { |
8660 // Can we get away with map check and not instance type check? | 8655 // Can we get away with map check and not instance type check? |
8661 Handle<Map> map = oracle()->GetCompareMap(expr); | 8656 Handle<Map> map = oracle()->GetCompareMap(expr); |
8662 if (!map.is_null()) { | 8657 if (!map.is_null()) { |
8663 AddInstruction(new(zone()) HCheckNonSmi(left)); | 8658 AddCheckMapsWithTransitions(left, map); |
8664 AddInstruction(HCheckMaps::NewWithTransitions(left, map, zone())); | 8659 AddCheckMapsWithTransitions(right, map); |
8665 AddInstruction(new(zone()) HCheckNonSmi(right)); | |
8666 AddInstruction(HCheckMaps::NewWithTransitions(right, map, zone())); | |
8667 HCompareObjectEqAndBranch* result = | 8660 HCompareObjectEqAndBranch* result = |
8668 new(zone()) HCompareObjectEqAndBranch(left, right); | 8661 new(zone()) HCompareObjectEqAndBranch(left, right); |
8669 result->set_position(expr->position()); | 8662 result->set_position(expr->position()); |
8670 return ast_context()->ReturnControl(result, expr->id()); | 8663 return ast_context()->ReturnControl(result, expr->id()); |
8671 } else { | 8664 } else { |
8672 AddInstruction(new(zone()) HCheckNonSmi(left)); | 8665 AddInstruction(new(zone()) HCheckNonSmi(left)); |
8673 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 8666 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
8674 AddInstruction(new(zone()) HCheckNonSmi(right)); | 8667 AddInstruction(new(zone()) HCheckNonSmi(right)); |
8675 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 8668 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
8676 HCompareObjectEqAndBranch* result = | 8669 HCompareObjectEqAndBranch* result = |
(...skipping 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9962 } | 9955 } |
9963 } | 9956 } |
9964 | 9957 |
9965 #ifdef DEBUG | 9958 #ifdef DEBUG |
9966 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9959 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
9967 if (allocator_ != NULL) allocator_->Verify(); | 9960 if (allocator_ != NULL) allocator_->Verify(); |
9968 #endif | 9961 #endif |
9969 } | 9962 } |
9970 | 9963 |
9971 } } // namespace v8::internal | 9964 } } // namespace v8::internal |
OLD | NEW |