Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: src/hydrogen.cc

Issue 11343011: Simplified HCheckMaps handling a bit. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased and polished Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698