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

Side by Side Diff: src/hydrogen.cc

Issue 23578030: Reland Handle non-JSObject heap objects using slow-path IC stub guarded by the map. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Filter non-jsmaps for keyed loads Created 7 years, 3 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/hydrogen.h ('k') | src/ic.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 3987 matching lines...) Expand 10 before | Expand all | Expand 10 after
3998 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, 3998 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context,
3999 literals, 3999 literals,
4000 expr->pattern(), 4000 expr->pattern(),
4001 expr->flags(), 4001 expr->flags(),
4002 expr->literal_index()); 4002 expr->literal_index());
4003 return ast_context()->ReturnInstruction(instr, expr->id()); 4003 return ast_context()->ReturnInstruction(instr, expr->id());
4004 } 4004 }
4005 4005
4006 4006
4007 static bool CanInlinePropertyAccess(Map* type) { 4007 static bool CanInlinePropertyAccess(Map* type) {
4008 return !type->is_dictionary_map() && !type->has_named_interceptor(); 4008 return type->IsJSObjectMap() &&
4009 !type->is_dictionary_map() &&
4010 !type->has_named_interceptor();
4009 } 4011 }
4010 4012
4011 4013
4012 static void LookupInPrototypes(Handle<Map> map, 4014 static void LookupInPrototypes(Handle<Map> map,
4013 Handle<String> name, 4015 Handle<String> name,
4014 LookupResult* lookup) { 4016 LookupResult* lookup) {
4015 while (map->prototype()->IsJSObject()) { 4017 while (map->prototype()->IsJSObject()) {
4016 Handle<JSObject> holder(JSObject::cast(map->prototype())); 4018 Handle<JSObject> holder(JSObject::cast(map->prototype()));
4017 map = Handle<Map>(holder->map()); 4019 map = Handle<Map>(holder->map());
4018 if (!CanInlinePropertyAccess(*map)) break; 4020 if (!CanInlinePropertyAccess(*map)) break;
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after
4613 LookupInPrototypes(map, name, &lookup); 4615 LookupInPrototypes(map, name, &lookup);
4614 if (!lookup.IsField()) return NULL; 4616 if (!lookup.IsField()) return NULL;
4615 4617
4616 BuildCheckHeapObject(object); 4618 BuildCheckHeapObject(object);
4617 Add<HCheckMaps>(object, types); 4619 Add<HCheckMaps>(object, types);
4618 4620
4619 Handle<JSObject> holder(lookup.holder()); 4621 Handle<JSObject> holder(lookup.holder());
4620 Handle<Map> holder_map(holder->map()); 4622 Handle<Map> holder_map(holder->map());
4621 HValue* checked_holder = BuildCheckPrototypeMaps( 4623 HValue* checked_holder = BuildCheckPrototypeMaps(
4622 Handle<JSObject>::cast(prototype), holder); 4624 Handle<JSObject>::cast(prototype), holder);
4625 ASSERT(holder_map->IsJSObjectMap());
Michael Starzinger 2013/09/12 21:41:38 This is virtually guaranteed, as we are loading th
4623 return BuildLoadNamedField(checked_holder, 4626 return BuildLoadNamedField(checked_holder,
4624 HObjectAccess::ForField(holder_map, &lookup, name)); 4627 HObjectAccess::ForField(holder_map, &lookup, name));
4625 } 4628 }
4626 4629
4627 4630
4628 // Returns true if an instance of this map can never find a property with this 4631 // Returns true if an instance of this map can never find a property with this
4629 // name in its prototype chain. This means all prototypes up to the top are 4632 // name in its prototype chain. This means all prototypes up to the top are
4630 // fast and don't have the name in them. It would be good if we could optimize 4633 // fast and don't have the name in them. It would be good if we could optimize
4631 // polymorphic loads where the property is sometimes found in the prototype 4634 // polymorphic loads where the property is sometimes found in the prototype
4632 // chain. 4635 // chain.
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after
5374 HCheckMaps* checked_object = AddCheckMap(object, map); 5377 HCheckMaps* checked_object = AddCheckMap(object, map);
5375 return New<HLoadNamedField>( 5378 return New<HLoadNamedField>(
5376 checked_object, HObjectAccess::ForArrayLength(map->elements_kind())); 5379 checked_object, HObjectAccess::ForArrayLength(map->elements_kind()));
5377 } 5380 }
5378 } 5381 }
5379 5382
5380 LookupResult lookup(isolate()); 5383 LookupResult lookup(isolate());
5381 map->LookupDescriptor(NULL, *name, &lookup); 5384 map->LookupDescriptor(NULL, *name, &lookup);
5382 if (lookup.IsField()) { 5385 if (lookup.IsField()) {
5383 HCheckMaps* checked_object = AddCheckMap(object, map); 5386 HCheckMaps* checked_object = AddCheckMap(object, map);
5387 ASSERT(map->IsJSObjectMap());
5384 return BuildLoadNamedField( 5388 return BuildLoadNamedField(
5385 checked_object, HObjectAccess::ForField(map, &lookup, name)); 5389 checked_object, HObjectAccess::ForField(map, &lookup, name));
5386 } 5390 }
5387 5391
5388 // Handle a load of a constant known function. 5392 // Handle a load of a constant known function.
5389 if (lookup.IsConstant()) { 5393 if (lookup.IsConstant()) {
5390 AddCheckMap(object, map); 5394 AddCheckMap(object, map);
5391 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); 5395 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
5392 return New<HConstant>(constant); 5396 return New<HConstant>(constant);
5393 } 5397 }
5394 5398
5399 if (lookup.IsFound()) {
5400 // Cannot handle the property, do a generic load instead.
5401 HValue* context = environment()->context();
5402 return new(zone()) HLoadNamedGeneric(context, object, name);
5403 }
5404
5395 // Handle a load from a known field somewhere in the prototype chain. 5405 // Handle a load from a known field somewhere in the prototype chain.
5396 LookupInPrototypes(map, name, &lookup); 5406 LookupInPrototypes(map, name, &lookup);
5397 if (lookup.IsField()) { 5407 if (lookup.IsField()) {
5398 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5408 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5399 Handle<JSObject> holder(lookup.holder()); 5409 Handle<JSObject> holder(lookup.holder());
5400 Handle<Map> holder_map(holder->map()); 5410 Handle<Map> holder_map(holder->map());
5401 AddCheckMap(object, map); 5411 AddCheckMap(object, map);
5402 HValue* checked_holder = BuildCheckPrototypeMaps(prototype, holder); 5412 HValue* checked_holder = BuildCheckPrototypeMaps(prototype, holder);
5413 ASSERT(holder_map->IsJSObjectMap());
Michael Starzinger 2013/09/12 21:41:38 Likewise.
5403 return BuildLoadNamedField( 5414 return BuildLoadNamedField(
5404 checked_holder, HObjectAccess::ForField(holder_map, &lookup, name)); 5415 checked_holder, HObjectAccess::ForField(holder_map, &lookup, name));
5405 } 5416 }
5406 5417
5407 // Handle a load of a constant function somewhere in the prototype chain. 5418 // Handle a load of a constant function somewhere in the prototype chain.
5408 if (lookup.IsConstant()) { 5419 if (lookup.IsConstant()) {
5409 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5420 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5410 Handle<JSObject> holder(lookup.holder()); 5421 Handle<JSObject> holder(lookup.holder());
5411 Handle<Map> holder_map(holder->map()); 5422 Handle<Map> holder_map(holder->map());
5412 AddCheckMap(object, map); 5423 AddCheckMap(object, map);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
5477 // much faster than transitioning the elements to the worst case, trading a 5488 // much faster than transitioning the elements to the worst case, trading a
5478 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. 5489 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
5479 bool has_double_maps = false; 5490 bool has_double_maps = false;
5480 bool has_smi_or_object_maps = false; 5491 bool has_smi_or_object_maps = false;
5481 bool has_js_array_access = false; 5492 bool has_js_array_access = false;
5482 bool has_non_js_array_access = false; 5493 bool has_non_js_array_access = false;
5483 bool has_seen_holey_elements = false; 5494 bool has_seen_holey_elements = false;
5484 Handle<Map> most_general_consolidated_map; 5495 Handle<Map> most_general_consolidated_map;
5485 for (int i = 0; i < maps->length(); ++i) { 5496 for (int i = 0; i < maps->length(); ++i) {
5486 Handle<Map> map = maps->at(i); 5497 Handle<Map> map = maps->at(i);
5498 if (!map->IsJSObjectMap()) return NULL;
5487 // Don't allow mixing of JSArrays with JSObjects. 5499 // Don't allow mixing of JSArrays with JSObjects.
5488 if (map->instance_type() == JS_ARRAY_TYPE) { 5500 if (map->instance_type() == JS_ARRAY_TYPE) {
5489 if (has_non_js_array_access) return NULL; 5501 if (has_non_js_array_access) return NULL;
5490 has_js_array_access = true; 5502 has_js_array_access = true;
5491 } else if (has_js_array_access) { 5503 } else if (has_js_array_access) {
5492 return NULL; 5504 return NULL;
5493 } else { 5505 } else {
5494 has_non_js_array_access = true; 5506 has_non_js_array_access = true;
5495 } 5507 }
5496 // Don't allow mixed, incompatible elements kinds. 5508 // Don't allow mixed, incompatible elements kinds.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
5529 consolidated_elements_kind, 5541 consolidated_elements_kind,
5530 false, NEVER_RETURN_HOLE, STANDARD_STORE); 5542 false, NEVER_RETURN_HOLE, STANDARD_STORE);
5531 return instr; 5543 return instr;
5532 } 5544 }
5533 5545
5534 5546
5535 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( 5547 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
5536 HValue* object, 5548 HValue* object,
5537 HValue* key, 5549 HValue* key,
5538 HValue* val, 5550 HValue* val,
5539 Expression* prop, 5551 SmallMapList* maps,
5540 BailoutId ast_id, 5552 BailoutId ast_id,
5541 int position, 5553 int position,
5542 bool is_store, 5554 bool is_store,
5543 KeyedAccessStoreMode store_mode, 5555 KeyedAccessStoreMode store_mode,
5544 bool* has_side_effects) { 5556 bool* has_side_effects) {
5545 *has_side_effects = false; 5557 *has_side_effects = false;
5546 BuildCheckHeapObject(object); 5558 BuildCheckHeapObject(object);
5547 SmallMapList* maps = prop->GetReceiverTypes();
5548 5559
5549 if (!is_store) { 5560 if (!is_store) {
5550 HInstruction* consolidated_load = 5561 HInstruction* consolidated_load =
5551 TryBuildConsolidatedElementLoad(object, key, val, maps); 5562 TryBuildConsolidatedElementLoad(object, key, val, maps);
5552 if (consolidated_load != NULL) { 5563 if (consolidated_load != NULL) {
5553 *has_side_effects |= consolidated_load->HasObservableSideEffects(); 5564 *has_side_effects |= consolidated_load->HasObservableSideEffects();
5554 if (position != RelocInfo::kNoPosition) { 5565 if (position != RelocInfo::kNoPosition) {
5555 consolidated_load->set_position(position); 5566 consolidated_load->set_position(position);
5556 } 5567 }
5557 return consolidated_load; 5568 return consolidated_load;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
5593 untransitionable_maps.Add(map); 5604 untransitionable_maps.Add(map);
5594 } 5605 }
5595 } 5606 }
5596 5607
5597 // If only one map is left after transitioning, handle this case 5608 // If only one map is left after transitioning, handle this case
5598 // monomorphically. 5609 // monomorphically.
5599 ASSERT(untransitionable_maps.length() >= 1); 5610 ASSERT(untransitionable_maps.length() >= 1);
5600 if (untransitionable_maps.length() == 1) { 5611 if (untransitionable_maps.length() == 1) {
5601 Handle<Map> untransitionable_map = untransitionable_maps[0]; 5612 Handle<Map> untransitionable_map = untransitionable_maps[0];
5602 HInstruction* instr = NULL; 5613 HInstruction* instr = NULL;
5603 if (untransitionable_map->has_slow_elements_kind()) { 5614 if (untransitionable_map->has_slow_elements_kind() ||
5615 !untransitionable_map->IsJSObjectMap()) {
5604 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 5616 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
5605 : BuildLoadKeyedGeneric(object, key)); 5617 : BuildLoadKeyedGeneric(object, key));
5606 } else { 5618 } else {
5607 instr = BuildMonomorphicElementAccess( 5619 instr = BuildMonomorphicElementAccess(
5608 object, key, val, transition, untransitionable_map, is_store, 5620 object, key, val, transition, untransitionable_map, is_store,
5609 store_mode); 5621 store_mode);
5610 } 5622 }
5611 *has_side_effects |= instr->HasObservableSideEffects(); 5623 *has_side_effects |= instr->HasObservableSideEffects();
5612 if (position != RelocInfo::kNoPosition) instr->set_position(position); 5624 if (position != RelocInfo::kNoPosition) instr->set_position(position);
5613 return is_store ? NULL : instr; 5625 return is_store ? NULL : instr;
5614 } 5626 }
5615 5627
5616 HBasicBlock* join = graph()->CreateBasicBlock(); 5628 HBasicBlock* join = graph()->CreateBasicBlock();
5617 5629
5618 for (int i = 0; i < untransitionable_maps.length(); ++i) { 5630 for (int i = 0; i < untransitionable_maps.length(); ++i) {
5619 Handle<Map> map = untransitionable_maps[i]; 5631 Handle<Map> map = untransitionable_maps[i];
5632 if (!map->IsJSObjectMap()) continue;
5620 ElementsKind elements_kind = map->elements_kind(); 5633 ElementsKind elements_kind = map->elements_kind();
5621 HBasicBlock* this_map = graph()->CreateBasicBlock(); 5634 HBasicBlock* this_map = graph()->CreateBasicBlock();
5622 HBasicBlock* other_map = graph()->CreateBasicBlock(); 5635 HBasicBlock* other_map = graph()->CreateBasicBlock();
5623 HCompareMap* mapcompare = 5636 HCompareMap* mapcompare =
5624 new(zone()) HCompareMap(object, map, this_map, other_map); 5637 new(zone()) HCompareMap(object, map, this_map, other_map);
5625 current_block()->Finish(mapcompare); 5638 current_block()->Finish(mapcompare);
5626 5639
5627 set_current_block(this_map); 5640 set_current_block(this_map);
5628 HInstruction* access = NULL; 5641 HInstruction* access = NULL;
5629 if (IsDictionaryElementsKind(elements_kind)) { 5642 if (IsDictionaryElementsKind(elements_kind)) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
5682 Handle<Map> map = types->first(); 5695 Handle<Map> map = types->first();
5683 if (map->has_slow_elements_kind()) { 5696 if (map->has_slow_elements_kind()) {
5684 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 5697 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
5685 : BuildLoadKeyedGeneric(obj, key); 5698 : BuildLoadKeyedGeneric(obj, key);
5686 AddInstruction(instr); 5699 AddInstruction(instr);
5687 } else { 5700 } else {
5688 BuildCheckHeapObject(obj); 5701 BuildCheckHeapObject(obj);
5689 instr = BuildMonomorphicElementAccess( 5702 instr = BuildMonomorphicElementAccess(
5690 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); 5703 obj, key, val, NULL, map, is_store, expr->GetStoreMode());
5691 } 5704 }
5692 } else if (expr->GetReceiverTypes() != NULL && 5705 } else if (types != NULL && !types->is_empty()) {
5693 !expr->GetReceiverTypes()->is_empty()) {
5694 return HandlePolymorphicElementAccess( 5706 return HandlePolymorphicElementAccess(
5695 obj, key, val, expr, ast_id, position, is_store, 5707 obj, key, val, types, ast_id, position, is_store,
5696 expr->GetStoreMode(), has_side_effects); 5708 expr->GetStoreMode(), has_side_effects);
5697 } else { 5709 } else {
5698 if (is_store) { 5710 if (is_store) {
5699 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { 5711 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) {
5700 Add<HDeoptimize>("Insufficient type feedback for keyed store", 5712 Add<HDeoptimize>("Insufficient type feedback for keyed store",
5701 Deoptimizer::SOFT); 5713 Deoptimizer::SOFT);
5702 } 5714 }
5703 instr = BuildStoreKeyedGeneric(obj, key, val); 5715 instr = BuildStoreKeyedGeneric(obj, key, val);
5704 } else { 5716 } else {
5705 if (expr->AsProperty()->IsUninitialized()) { 5717 if (expr->AsProperty()->IsUninitialized()) {
(...skipping 3974 matching lines...) Expand 10 before | Expand all | Expand 10 after
9680 if (ShouldProduceTraceOutput()) { 9692 if (ShouldProduceTraceOutput()) {
9681 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9693 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9682 } 9694 }
9683 9695
9684 #ifdef DEBUG 9696 #ifdef DEBUG
9685 graph_->Verify(false); // No full verify. 9697 graph_->Verify(false); // No full verify.
9686 #endif 9698 #endif
9687 } 9699 }
9688 9700
9689 } } // namespace v8::internal 9701 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698