| 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 |