OLD | NEW |
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 5334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5345 if (access.representation().IsDouble()) { | 5345 if (access.representation().IsDouble()) { |
5346 // Load the heap number. | 5346 // Load the heap number. |
5347 checked_object = Add<HLoadNamedField>( | 5347 checked_object = Add<HLoadNamedField>( |
5348 checked_object, static_cast<HValue*>(NULL), | 5348 checked_object, static_cast<HValue*>(NULL), |
5349 access.WithRepresentation(Representation::Tagged())); | 5349 access.WithRepresentation(Representation::Tagged())); |
5350 checked_object->set_type(HType::HeapNumber()); | 5350 checked_object->set_type(HType::HeapNumber()); |
5351 // Load the double value from it. | 5351 // Load the double value from it. |
5352 access = HObjectAccess::ForHeapNumberValue(); | 5352 access = HObjectAccess::ForHeapNumberValue(); |
5353 } | 5353 } |
5354 return New<HLoadNamedField>( | 5354 return New<HLoadNamedField>( |
5355 checked_object, static_cast<HValue*>(NULL), access); | 5355 checked_object, static_cast<HValue*>(NULL), access, info->field_map()); |
5356 } | 5356 } |
5357 | 5357 |
5358 | 5358 |
5359 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 5359 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( |
5360 PropertyAccessInfo* info, | 5360 PropertyAccessInfo* info, |
5361 HValue* checked_object, | 5361 HValue* checked_object, |
5362 HValue* value) { | 5362 HValue* value) { |
5363 bool transition_to_field = info->lookup()->IsTransition(); | 5363 bool transition_to_field = info->lookup()->IsTransition(); |
5364 // TODO(verwaest): Move this logic into PropertyAccessInfo. | 5364 // TODO(verwaest): Move this logic into PropertyAccessInfo. |
5365 HObjectAccess field_access = HObjectAccess::ForField( | 5365 HObjectAccess field_access = HObjectAccess::ForField( |
(...skipping 24 matching lines...) Expand all Loading... |
5390 } else { | 5390 } else { |
5391 // Already holds a HeapNumber; load the box and write its value field. | 5391 // Already holds a HeapNumber; load the box and write its value field. |
5392 HInstruction* heap_number = Add<HLoadNamedField>( | 5392 HInstruction* heap_number = Add<HLoadNamedField>( |
5393 checked_object, static_cast<HValue*>(NULL), heap_number_access); | 5393 checked_object, static_cast<HValue*>(NULL), heap_number_access); |
5394 heap_number->set_type(HType::HeapNumber()); | 5394 heap_number->set_type(HType::HeapNumber()); |
5395 instr = New<HStoreNamedField>(heap_number, | 5395 instr = New<HStoreNamedField>(heap_number, |
5396 HObjectAccess::ForHeapNumberValue(), | 5396 HObjectAccess::ForHeapNumberValue(), |
5397 value, STORE_TO_INITIALIZED_ENTRY); | 5397 value, STORE_TO_INITIALIZED_ENTRY); |
5398 } | 5398 } |
5399 } else { | 5399 } else { |
| 5400 if (!info->field_map().is_null()) { |
| 5401 ASSERT(field_access.representation().IsHeapObject()); |
| 5402 BuildCheckHeapObject(value); |
| 5403 value = BuildCheckMap(value, info->field_map()); |
| 5404 } |
| 5405 |
5400 // This is a normal store. | 5406 // This is a normal store. |
5401 instr = New<HStoreNamedField>( | 5407 instr = New<HStoreNamedField>( |
5402 checked_object->ActualValue(), field_access, value, | 5408 checked_object->ActualValue(), field_access, value, |
5403 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY); | 5409 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY); |
5404 } | 5410 } |
5405 | 5411 |
5406 if (transition_to_field) { | 5412 if (transition_to_field) { |
5407 HConstant* transition_constant = Add<HConstant>(info->transition()); | 5413 HConstant* transition_constant = Add<HConstant>(info->transition()); |
5408 instr->SetTransition(transition_constant, top_info()); | 5414 instr->SetTransition(transition_constant, top_info()); |
5409 instr->SetChangesFlag(kMaps); | 5415 instr->SetChangesFlag(kMaps); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5453 if (!info->lookup_.IsField()) return false; | 5459 if (!info->lookup_.IsField()) return false; |
5454 | 5460 |
5455 Representation r = access_.representation(); | 5461 Representation r = access_.representation(); |
5456 if (IsLoad()) { | 5462 if (IsLoad()) { |
5457 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; | 5463 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; |
5458 } else { | 5464 } else { |
5459 if (!info->access_.representation().IsCompatibleForStore(r)) return false; | 5465 if (!info->access_.representation().IsCompatibleForStore(r)) return false; |
5460 } | 5466 } |
5461 if (info->access_.offset() != access_.offset()) return false; | 5467 if (info->access_.offset() != access_.offset()) return false; |
5462 if (info->access_.IsInobject() != access_.IsInobject()) return false; | 5468 if (info->access_.IsInobject() != access_.IsInobject()) return false; |
| 5469 if (!field_map_.is_identical_to(info->field_map_)) { |
| 5470 if (!IsLoad()) return false; |
| 5471 |
| 5472 // Throw away type information for merging polymorphic loads. |
| 5473 field_map_ = info->field_map_ = Handle<Map>(); |
| 5474 } |
5463 info->GeneralizeRepresentation(r); | 5475 info->GeneralizeRepresentation(r); |
5464 return true; | 5476 return true; |
5465 } | 5477 } |
5466 | 5478 |
5467 | 5479 |
5468 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { | 5480 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { |
5469 if (!type_->IsClass()) return true; | 5481 if (!type_->IsClass()) return true; |
5470 map()->LookupDescriptor(NULL, *name_, &lookup_); | 5482 map()->LookupDescriptor(NULL, *name_, &lookup_); |
5471 return LoadResult(map()); | 5483 return LoadResult(map()); |
5472 } | 5484 } |
5473 | 5485 |
5474 | 5486 |
5475 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { | 5487 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { |
5476 if (!IsLoad() && lookup_.IsProperty() && | 5488 if (!IsLoad() && lookup_.IsProperty() && |
5477 (lookup_.IsReadOnly() || !lookup_.IsCacheable())) { | 5489 (lookup_.IsReadOnly() || !lookup_.IsCacheable())) { |
5478 return false; | 5490 return false; |
5479 } | 5491 } |
5480 | 5492 |
5481 if (lookup_.IsField()) { | 5493 if (lookup_.IsField()) { |
| 5494 // Construct the object field access. |
5482 access_ = HObjectAccess::ForField(map, &lookup_, name_); | 5495 access_ = HObjectAccess::ForField(map, &lookup_, name_); |
| 5496 |
| 5497 if (access_.representation().IsHeapObject()) { |
| 5498 // Figure out the field type from the accessor map. |
| 5499 HeapType* field_type = lookup_.GetFieldTypeFromMap(*map); |
| 5500 if (field_type->IsClass()) { |
| 5501 Handle<Map> field_map = field_type->AsClass(); |
| 5502 if (field_map->is_stable()) { // TODO(bmeurer) |
| 5503 field_map_ = field_map; |
| 5504 field_map_->AddDependentCompilationInfo( |
| 5505 DependentCode::kPrototypeCheckGroup, top_info()); |
| 5506 |
| 5507 // Add dependency on the map that introduced the field. |
| 5508 Handle<Map> field_owner = handle(lookup_.GetFieldOwnerFromMap(*map)); |
| 5509 field_owner->AddDependentCompilationInfo( |
| 5510 DependentCode::kFieldTypeGroup, top_info()); |
| 5511 } |
| 5512 } |
| 5513 } |
5483 } else if (lookup_.IsPropertyCallbacks()) { | 5514 } else if (lookup_.IsPropertyCallbacks()) { |
5484 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); | 5515 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); |
5485 if (!callback->IsAccessorPair()) return false; | 5516 if (!callback->IsAccessorPair()) return false; |
5486 Object* raw_accessor = IsLoad() | 5517 Object* raw_accessor = IsLoad() |
5487 ? Handle<AccessorPair>::cast(callback)->getter() | 5518 ? Handle<AccessorPair>::cast(callback)->getter() |
5488 : Handle<AccessorPair>::cast(callback)->setter(); | 5519 : Handle<AccessorPair>::cast(callback)->setter(); |
5489 if (!raw_accessor->IsJSFunction()) return false; | 5520 if (!raw_accessor->IsJSFunction()) return false; |
5490 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); | 5521 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); |
5491 if (accessor->shared()->IsApiFunction()) { | 5522 if (accessor->shared()->IsApiFunction()) { |
5492 CallOptimization call_optimization(accessor); | 5523 CallOptimization call_optimization(accessor); |
(...skipping 6045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11538 if (ShouldProduceTraceOutput()) { | 11569 if (ShouldProduceTraceOutput()) { |
11539 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11570 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11540 } | 11571 } |
11541 | 11572 |
11542 #ifdef DEBUG | 11573 #ifdef DEBUG |
11543 graph_->Verify(false); // No full verify. | 11574 graph_->Verify(false); // No full verify. |
11544 #endif | 11575 #endif |
11545 } | 11576 } |
11546 | 11577 |
11547 } } // namespace v8::internal | 11578 } } // namespace v8::internal |
OLD | NEW |