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

Side by Side Diff: src/hydrogen.cc

Issue 22213002: Replace LoadNamedFieldPolymorphic with explicit branches. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 4 months 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/arm/lithium-codegen-arm.cc ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 4595 matching lines...) Expand 10 before | Expand all | Expand 10 after
4606 4606
4607 Handle<JSObject> holder(lookup.holder()); 4607 Handle<JSObject> holder(lookup.holder());
4608 Handle<Map> holder_map(holder->map()); 4608 Handle<Map> holder_map(holder->map());
4609 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder); 4609 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder);
4610 HValue* holder_value = Add<HConstant>(holder); 4610 HValue* holder_value = Add<HConstant>(holder);
4611 return BuildLoadNamedField(holder_value, 4611 return BuildLoadNamedField(holder_value,
4612 HObjectAccess::ForField(holder_map, &lookup, name)); 4612 HObjectAccess::ForField(holder_map, &lookup, name));
4613 } 4613 }
4614 4614
4615 4615
4616 // Returns true if an instance of this map can never find a property with this
4617 // name in its prototype chain. This means all prototypes up to the top are
4618 // fast and don't have the name in them. It would be good if we could optimize
4619 // polymorphic loads where the property is sometimes found in the prototype
4620 // chain.
4621 static bool PrototypeChainCanNeverResolve(
4622 Handle<Map> map, Handle<String> name) {
4623 Isolate* isolate = map->GetIsolate();
4624 Object* current = map->prototype();
4625 while (current != isolate->heap()->null_value()) {
4626 if (current->IsJSGlobalProxy() ||
4627 current->IsGlobalObject() ||
4628 !current->IsJSObject() ||
4629 JSObject::cast(current)->map()->has_named_interceptor() ||
4630 JSObject::cast(current)->IsAccessCheckNeeded() ||
4631 !JSObject::cast(current)->HasFastProperties()) {
4632 return false;
4633 }
4634
4635 LookupResult lookup(isolate);
4636 Map* map = JSObject::cast(current)->map();
4637 map->LookupDescriptor(NULL, *name, &lookup);
4638 if (lookup.IsFound()) return false;
4639 if (!lookup.IsCacheable()) return false;
4640 current = JSObject::cast(current)->GetPrototype();
4641 }
4642 return true;
4643 }
4644
4645
4616 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 4646 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
4617 Property* expr, 4647 Property* expr,
4618 HValue* object, 4648 HValue* object,
4619 SmallMapList* types, 4649 SmallMapList* types,
4620 Handle<String> name) { 4650 Handle<String> name) {
4621 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( 4651 HInstruction* instr = TryLoadPolymorphicAsMonomorphic(
4622 expr, object, types, name); 4652 expr, object, types, name);
4623 if (instr == NULL) { 4653 if (instr != NULL) {
4624 // Something did not match; must use a polymorphic load. 4654 instr->set_position(expr->position());
4625 BuildCheckHeapObject(object); 4655 return ast_context()->ReturnInstruction(instr, expr->id());
4626 HValue* context = environment()->context();
4627 instr = new(zone()) HLoadNamedFieldPolymorphic(
4628 context, object, types, name, zone());
4629 } 4656 }
4630 4657
4631 instr->set_position(expr->position()); 4658 // Something did not match; must use a polymorphic load.
4632 return ast_context()->ReturnInstruction(instr, expr->id()); 4659 int count = 0;
4660 HBasicBlock* join = NULL;
4661 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
4662 Handle<Map> map = types->at(i);
4663 LookupResult lookup(isolate());
4664 if (ComputeLoadStoreField(map, name, &lookup, false) ||
4665 (lookup.IsCacheable() &&
4666 !map->is_dictionary_map() &&
4667 !map->has_named_interceptor() &&
4668 (lookup.IsConstant() ||
4669 (!lookup.IsFound() &&
4670 PrototypeChainCanNeverResolve(map, name))))) {
4671 if (count == 0) {
4672 BuildCheckHeapObject(object);
4673 join = graph()->CreateBasicBlock();
4674 }
4675 ++count;
4676 HBasicBlock* if_true = graph()->CreateBasicBlock();
4677 HBasicBlock* if_false = graph()->CreateBasicBlock();
4678 HCompareMap* compare =
4679 new(zone()) HCompareMap(object, map, if_true, if_false);
4680 current_block()->Finish(compare);
4681
4682 set_current_block(if_true);
4683
4684 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic.
4685 if (lookup.IsField()) {
4686 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name);
4687 HLoadNamedField* load = BuildLoadNamedField(object, access);
4688 load->set_position(expr->position());
4689 AddInstruction(load);
4690 if (!ast_context()->IsEffect()) Push(load);
4691 } else if (lookup.IsConstant()) {
4692 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
4693 HConstant* hconstant = Add<HConstant>(constant);
4694 if (!ast_context()->IsEffect()) Push(hconstant);
4695 } else {
4696 ASSERT(!lookup.IsFound());
4697 if (map->prototype()->IsJSObject()) {
4698 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
4699 Handle<JSObject> holder = prototype;
4700 while (holder->map()->prototype()->IsJSObject()) {
4701 holder = handle(JSObject::cast(holder->map()->prototype()));
4702 }
4703 BuildCheckPrototypeMaps(prototype, holder);
4704 }
4705 if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
4706 }
4707
4708 current_block()->Goto(join);
4709 set_current_block(if_false);
4710 }
4711 }
4712
4713 // Finish up. Unconditionally deoptimize if we've handled all the maps we
4714 // know about and do not want to handle ones we've never seen. Otherwise
4715 // use a generic IC.
4716 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
4717 FinishExitWithHardDeoptimization(join);
4718 } else {
4719 HInstruction* load = BuildLoadNamedGeneric(object, name, expr);
4720 load->set_position(expr->position());
4721 AddInstruction(load);
4722 if (!ast_context()->IsEffect()) Push(load);
4723
4724 if (join != NULL) {
4725 current_block()->Goto(join);
4726 } else {
4727 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
4728 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
4729 return;
4730 }
4731 }
4732
4733 ASSERT(join != NULL);
4734 join->SetJoinId(expr->id());
4735 set_current_block(join);
4736 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
4633 } 4737 }
4634 4738
4635 4739
4636 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( 4740 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
4637 int position, 4741 int position,
4638 BailoutId assignment_id, 4742 BailoutId assignment_id,
4639 HValue* object, 4743 HValue* object,
4640 HValue* store_value, 4744 HValue* store_value,
4641 HValue* result_value, 4745 HValue* result_value,
4642 SmallMapList* types, 4746 SmallMapList* types,
(...skipping 5086 matching lines...) Expand 10 before | Expand all | Expand 10 after
9729 if (ShouldProduceTraceOutput()) { 9833 if (ShouldProduceTraceOutput()) {
9730 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9834 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9731 } 9835 }
9732 9836
9733 #ifdef DEBUG 9837 #ifdef DEBUG
9734 graph_->Verify(false); // No full verify. 9838 graph_->Verify(false); // No full verify.
9735 #endif 9839 #endif
9736 } 9840 }
9737 9841
9738 } } // namespace v8::internal 9842 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.cc ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698