| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/v8.h" | 9 #include "src/v8.h" |
| 10 | 10 |
| (...skipping 5378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5389 HObjectAccess::ForContextSlot(lookup.slot_index)); | 5389 HObjectAccess::ForContextSlot(lookup.slot_index)); |
| 5390 return ast_context()->ReturnInstruction(result, expr->id()); | 5390 return ast_context()->ReturnInstruction(result, expr->id()); |
| 5391 } | 5391 } |
| 5392 } | 5392 } |
| 5393 | 5393 |
| 5394 LookupIterator it(global, variable->name(), LookupIterator::OWN); | 5394 LookupIterator it(global, variable->name(), LookupIterator::OWN); |
| 5395 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); | 5395 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); |
| 5396 | 5396 |
| 5397 if (type == kUseCell) { | 5397 if (type == kUseCell) { |
| 5398 Handle<PropertyCell> cell = it.GetPropertyCell(); | 5398 Handle<PropertyCell> cell = it.GetPropertyCell(); |
| 5399 PropertyCell::AddDependentCompilationInfo(cell, top_info()); | 5399 top_info()->dependencies()->AssumePropertyCell(cell); |
| 5400 if (it.property_details().cell_type() == PropertyCellType::kConstant) { | 5400 if (it.property_details().cell_type() == PropertyCellType::kConstant) { |
| 5401 Handle<Object> constant_object(cell->value(), isolate()); | 5401 Handle<Object> constant_object(cell->value(), isolate()); |
| 5402 if (constant_object->IsConsString()) { | 5402 if (constant_object->IsConsString()) { |
| 5403 constant_object = | 5403 constant_object = |
| 5404 String::Flatten(Handle<String>::cast(constant_object)); | 5404 String::Flatten(Handle<String>::cast(constant_object)); |
| 5405 } | 5405 } |
| 5406 HConstant* constant = New<HConstant>(constant_object); | 5406 HConstant* constant = New<HConstant>(constant_object); |
| 5407 return ast_context()->ReturnInstruction(constant, expr->id()); | 5407 return ast_context()->ReturnInstruction(constant, expr->id()); |
| 5408 } else { | 5408 } else { |
| 5409 HConstant* cell_constant = Add<HConstant>(cell); | 5409 HConstant* cell_constant = Add<HConstant>(cell); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5770 Add<HConstant>(literal_index), | 5770 Add<HConstant>(literal_index), |
| 5771 Add<HConstant>(constants), | 5771 Add<HConstant>(constants), |
| 5772 Add<HConstant>(flags)); | 5772 Add<HConstant>(flags)); |
| 5773 | 5773 |
| 5774 Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral; | 5774 Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral; |
| 5775 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 5775 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| 5776 Runtime::FunctionForId(function_id), | 5776 Runtime::FunctionForId(function_id), |
| 5777 4); | 5777 4); |
| 5778 | 5778 |
| 5779 // Register to deopt if the boilerplate ElementsKind changes. | 5779 // Register to deopt if the boilerplate ElementsKind changes. |
| 5780 AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info()); | 5780 top_info()->dependencies()->AssumeTransitionStable(site); |
| 5781 } | 5781 } |
| 5782 | 5782 |
| 5783 // The array is expected in the bailout environment during computation | 5783 // The array is expected in the bailout environment during computation |
| 5784 // of the property values and is the value of the entire expression. | 5784 // of the property values and is the value of the entire expression. |
| 5785 Push(literal); | 5785 Push(literal); |
| 5786 // The literal index is on the stack, too. | 5786 // The literal index is on the stack, too. |
| 5787 Push(Add<HConstant>(expr->literal_index())); | 5787 Push(Add<HConstant>(expr->literal_index())); |
| 5788 | 5788 |
| 5789 HInstruction* elements = NULL; | 5789 HInstruction* elements = NULL; |
| 5790 | 5790 |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6085 } | 6085 } |
| 6086 | 6086 |
| 6087 field_maps_.Sort(); | 6087 field_maps_.Sort(); |
| 6088 DCHECK_EQ(num_field_maps, field_maps_.length()); | 6088 DCHECK_EQ(num_field_maps, field_maps_.length()); |
| 6089 | 6089 |
| 6090 // Determine field HType from field HeapType. | 6090 // Determine field HType from field HeapType. |
| 6091 field_type_ = HType::FromType<HeapType>(field_type); | 6091 field_type_ = HType::FromType<HeapType>(field_type); |
| 6092 DCHECK(field_type_.IsHeapObject()); | 6092 DCHECK(field_type_.IsHeapObject()); |
| 6093 | 6093 |
| 6094 // Add dependency on the map that introduced the field. | 6094 // Add dependency on the map that introduced the field. |
| 6095 Map::AddDependentCompilationInfo(GetFieldOwnerFromMap(map), | 6095 top_info()->dependencies()->AssumeFieldType(GetFieldOwnerFromMap(map)); |
| 6096 DependentCode::kFieldTypeGroup, top_info()); | |
| 6097 return true; | 6096 return true; |
| 6098 } | 6097 } |
| 6099 | 6098 |
| 6100 | 6099 |
| 6101 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { | 6100 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { |
| 6102 Handle<Map> map = this->map(); | 6101 Handle<Map> map = this->map(); |
| 6103 | 6102 |
| 6104 while (map->prototype()->IsJSObject()) { | 6103 while (map->prototype()->IsJSObject()) { |
| 6105 holder_ = handle(JSObject::cast(map->prototype())); | 6104 holder_ = handle(JSObject::cast(map->prototype())); |
| 6106 if (holder_->map()->is_deprecated()) { | 6105 if (holder_->map()->is_deprecated()) { |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6556 DCHECK(instr->HasObservableSideEffects()); | 6555 DCHECK(instr->HasObservableSideEffects()); |
| 6557 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6556 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6558 return; | 6557 return; |
| 6559 } | 6558 } |
| 6560 } | 6559 } |
| 6561 | 6560 |
| 6562 LookupIterator it(global, var->name(), LookupIterator::OWN); | 6561 LookupIterator it(global, var->name(), LookupIterator::OWN); |
| 6563 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); | 6562 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); |
| 6564 if (type == kUseCell) { | 6563 if (type == kUseCell) { |
| 6565 Handle<PropertyCell> cell = it.GetPropertyCell(); | 6564 Handle<PropertyCell> cell = it.GetPropertyCell(); |
| 6566 PropertyCell::AddDependentCompilationInfo(cell, top_info()); | 6565 top_info()->dependencies()->AssumePropertyCell(cell); |
| 6567 if (it.property_details().cell_type() == PropertyCellType::kConstant) { | 6566 if (it.property_details().cell_type() == PropertyCellType::kConstant) { |
| 6568 Handle<Object> constant(cell->value(), isolate()); | 6567 Handle<Object> constant(cell->value(), isolate()); |
| 6569 if (value->IsConstant()) { | 6568 if (value->IsConstant()) { |
| 6570 HConstant* c_value = HConstant::cast(value); | 6569 HConstant* c_value = HConstant::cast(value); |
| 6571 if (!constant.is_identical_to(c_value->handle(isolate()))) { | 6570 if (!constant.is_identical_to(c_value->handle(isolate()))) { |
| 6572 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, | 6571 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, |
| 6573 Deoptimizer::EAGER); | 6572 Deoptimizer::EAGER); |
| 6574 } | 6573 } |
| 6575 } else { | 6574 } else { |
| 6576 HValue* c_constant = Add<HConstant>(constant); | 6575 HValue* c_constant = Add<HConstant>(constant); |
| (...skipping 2773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9350 int argument_count, | 9349 int argument_count, |
| 9351 Handle<AllocationSite> site) { | 9350 Handle<AllocationSite> site) { |
| 9352 DCHECK(!site.is_null()); | 9351 DCHECK(!site.is_null()); |
| 9353 DCHECK(argument_count >= 0 && argument_count <= 1); | 9352 DCHECK(argument_count >= 0 && argument_count <= 1); |
| 9354 NoObservableSideEffectsScope no_effects(this); | 9353 NoObservableSideEffectsScope no_effects(this); |
| 9355 | 9354 |
| 9356 // We should at least have the constructor on the expression stack. | 9355 // We should at least have the constructor on the expression stack. |
| 9357 HValue* constructor = environment()->ExpressionStackAt(argument_count); | 9356 HValue* constructor = environment()->ExpressionStackAt(argument_count); |
| 9358 | 9357 |
| 9359 // Register on the site for deoptimization if the transition feedback changes. | 9358 // Register on the site for deoptimization if the transition feedback changes. |
| 9360 AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info()); | 9359 top_info()->dependencies()->AssumeTransitionStable(site); |
| 9361 ElementsKind kind = site->GetElementsKind(); | 9360 ElementsKind kind = site->GetElementsKind(); |
| 9362 HInstruction* site_instruction = Add<HConstant>(site); | 9361 HInstruction* site_instruction = Add<HConstant>(site); |
| 9363 | 9362 |
| 9364 // In the single constant argument case, we may have to adjust elements kind | 9363 // In the single constant argument case, we may have to adjust elements kind |
| 9365 // to avoid creating a packed non-empty array. | 9364 // to avoid creating a packed non-empty array. |
| 9366 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { | 9365 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { |
| 9367 HValue* argument = environment()->Top(); | 9366 HValue* argument = environment()->Top(); |
| 9368 if (argument->IsConstant()) { | 9367 if (argument->IsConstant()) { |
| 9369 HConstant* constant_argument = HConstant::cast(argument); | 9368 HConstant* constant_argument = HConstant::cast(argument); |
| 9370 DCHECK(constant_argument->HasSmiValue()); | 9369 DCHECK(constant_argument->HasSmiValue()); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9486 | 9485 |
| 9487 // Allocate an instance of the implicit receiver object. | 9486 // Allocate an instance of the implicit receiver object. |
| 9488 HValue* size_in_bytes = Add<HConstant>(instance_size); | 9487 HValue* size_in_bytes = Add<HConstant>(instance_size); |
| 9489 HAllocationMode allocation_mode; | 9488 HAllocationMode allocation_mode; |
| 9490 if (FLAG_pretenuring_call_new) { | 9489 if (FLAG_pretenuring_call_new) { |
| 9491 if (FLAG_allocation_site_pretenuring) { | 9490 if (FLAG_allocation_site_pretenuring) { |
| 9492 // Try to use pretenuring feedback. | 9491 // Try to use pretenuring feedback. |
| 9493 Handle<AllocationSite> allocation_site = expr->allocation_site(); | 9492 Handle<AllocationSite> allocation_site = expr->allocation_site(); |
| 9494 allocation_mode = HAllocationMode(allocation_site); | 9493 allocation_mode = HAllocationMode(allocation_site); |
| 9495 // Take a dependency on allocation site. | 9494 // Take a dependency on allocation site. |
| 9496 AllocationSite::RegisterForDeoptOnTenureChange(allocation_site, | 9495 top_info()->dependencies()->AssumeTenuringDecision(allocation_site); |
| 9497 top_info()); | |
| 9498 } | 9496 } |
| 9499 } | 9497 } |
| 9500 | 9498 |
| 9501 HAllocate* receiver = BuildAllocate( | 9499 HAllocate* receiver = BuildAllocate( |
| 9502 size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode); | 9500 size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode); |
| 9503 receiver->set_known_initial_map(initial_map); | 9501 receiver->set_known_initial_map(initial_map); |
| 9504 | 9502 |
| 9505 // Initialize map and fields of the newly allocated object. | 9503 // Initialize map and fields of the newly allocated object. |
| 9506 { NoObservableSideEffectsScope no_effects(this); | 9504 { NoObservableSideEffectsScope no_effects(this); |
| 9507 DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE); | 9505 DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 9531 // Replace the constructor function with a newly allocated receiver using | 9529 // Replace the constructor function with a newly allocated receiver using |
| 9532 // the index of the receiver from the top of the expression stack. | 9530 // the index of the receiver from the top of the expression stack. |
| 9533 const int receiver_index = argument_count - 1; | 9531 const int receiver_index = argument_count - 1; |
| 9534 DCHECK(environment()->ExpressionStackAt(receiver_index) == function); | 9532 DCHECK(environment()->ExpressionStackAt(receiver_index) == function); |
| 9535 environment()->SetExpressionStackAt(receiver_index, receiver); | 9533 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 9536 | 9534 |
| 9537 if (TryInlineConstruct(expr, receiver)) { | 9535 if (TryInlineConstruct(expr, receiver)) { |
| 9538 // Inlining worked, add a dependency on the initial map to make sure that | 9536 // Inlining worked, add a dependency on the initial map to make sure that |
| 9539 // this code is deoptimized whenever the initial map of the constructor | 9537 // this code is deoptimized whenever the initial map of the constructor |
| 9540 // changes. | 9538 // changes. |
| 9541 Map::AddDependentCompilationInfo( | 9539 top_info()->dependencies()->AssumeInitialMapCantChange(initial_map); |
| 9542 initial_map, DependentCode::kInitialMapChangedGroup, top_info()); | |
| 9543 return; | 9540 return; |
| 9544 } | 9541 } |
| 9545 | 9542 |
| 9546 // TODO(mstarzinger): For now we remove the previous HAllocate and all | 9543 // TODO(mstarzinger): For now we remove the previous HAllocate and all |
| 9547 // corresponding instructions and instead add HPushArguments for the | 9544 // corresponding instructions and instead add HPushArguments for the |
| 9548 // arguments in case inlining failed. What we actually should do is for | 9545 // arguments in case inlining failed. What we actually should do is for |
| 9549 // inlining to try to build a subgraph without mutating the parent graph. | 9546 // inlining to try to build a subgraph without mutating the parent graph. |
| 9550 HInstruction* instr = current_block()->last(); | 9547 HInstruction* instr = current_block()->last(); |
| 9551 do { | 9548 do { |
| 9552 HInstruction* prev_instr = instr->previous(); | 9549 HInstruction* prev_instr = instr->previous(); |
| (...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10506 if (!left_string.is_null() && !right_string.is_null()) { | 10503 if (!left_string.is_null() && !right_string.is_null()) { |
| 10507 return AddUncasted<HStringAdd>( | 10504 return AddUncasted<HStringAdd>( |
| 10508 left, right, allocation_mode.GetPretenureMode(), | 10505 left, right, allocation_mode.GetPretenureMode(), |
| 10509 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); | 10506 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); |
| 10510 } | 10507 } |
| 10511 | 10508 |
| 10512 // Register the dependent code with the allocation site. | 10509 // Register the dependent code with the allocation site. |
| 10513 if (!allocation_mode.feedback_site().is_null()) { | 10510 if (!allocation_mode.feedback_site().is_null()) { |
| 10514 DCHECK(!graph()->info()->IsStub()); | 10511 DCHECK(!graph()->info()->IsStub()); |
| 10515 Handle<AllocationSite> site(allocation_mode.feedback_site()); | 10512 Handle<AllocationSite> site(allocation_mode.feedback_site()); |
| 10516 AllocationSite::RegisterForDeoptOnTenureChange(site, top_info()); | 10513 top_info()->dependencies()->AssumeTenuringDecision(site); |
| 10517 } | 10514 } |
| 10518 | 10515 |
| 10519 // Inline the string addition into the stub when creating allocation | 10516 // Inline the string addition into the stub when creating allocation |
| 10520 // mementos to gather allocation site feedback, or if we can statically | 10517 // mementos to gather allocation site feedback, or if we can statically |
| 10521 // infer that we're going to create a cons string. | 10518 // infer that we're going to create a cons string. |
| 10522 if ((graph()->info()->IsStub() && | 10519 if ((graph()->info()->IsStub() && |
| 10523 allocation_mode.CreateAllocationMementos()) || | 10520 allocation_mode.CreateAllocationMementos()) || |
| 10524 (left->IsConstant() && | 10521 (left->IsConstant() && |
| 10525 HConstant::cast(left)->HasStringValue() && | 10522 HConstant::cast(left)->HasStringValue() && |
| 10526 HConstant::cast(left)->StringValue()->length() + 1 >= | 10523 HConstant::cast(left)->StringValue()->length() + 1 >= |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11077 | 11074 |
| 11078 HType type = instance_type == JS_ARRAY_TYPE | 11075 HType type = instance_type == JS_ARRAY_TYPE |
| 11079 ? HType::JSArray() : HType::JSObject(); | 11076 ? HType::JSArray() : HType::JSObject(); |
| 11080 HValue* object_size_constant = Add<HConstant>( | 11077 HValue* object_size_constant = Add<HConstant>( |
| 11081 boilerplate_object->map()->instance_size()); | 11078 boilerplate_object->map()->instance_size()); |
| 11082 | 11079 |
| 11083 PretenureFlag pretenure_flag = NOT_TENURED; | 11080 PretenureFlag pretenure_flag = NOT_TENURED; |
| 11084 Handle<AllocationSite> current_site(*site_context->current(), isolate()); | 11081 Handle<AllocationSite> current_site(*site_context->current(), isolate()); |
| 11085 if (FLAG_allocation_site_pretenuring) { | 11082 if (FLAG_allocation_site_pretenuring) { |
| 11086 pretenure_flag = current_site->GetPretenureMode(); | 11083 pretenure_flag = current_site->GetPretenureMode(); |
| 11087 AllocationSite::RegisterForDeoptOnTenureChange(current_site, top_info()); | 11084 top_info()->dependencies()->AssumeTenuringDecision(current_site); |
| 11088 } | 11085 } |
| 11089 | 11086 |
| 11090 AllocationSite::RegisterForDeoptOnTransitionChange(current_site, top_info()); | 11087 top_info()->dependencies()->AssumeTransitionStable(current_site); |
| 11091 | 11088 |
| 11092 HInstruction* object = Add<HAllocate>( | 11089 HInstruction* object = Add<HAllocate>( |
| 11093 object_size_constant, type, pretenure_flag, instance_type, current_site); | 11090 object_size_constant, type, pretenure_flag, instance_type, current_site); |
| 11094 | 11091 |
| 11095 // If allocation folding reaches Page::kMaxRegularHeapObjectSize the | 11092 // If allocation folding reaches Page::kMaxRegularHeapObjectSize the |
| 11096 // elements array may not get folded into the object. Hence, we set the | 11093 // elements array may not get folded into the object. Hence, we set the |
| 11097 // elements pointer to empty fixed array and let store elimination remove | 11094 // elements pointer to empty fixed array and let store elimination remove |
| 11098 // this store in the folding case. | 11095 // this store in the folding case. |
| 11099 HConstant* empty_fixed_array = Add<HConstant>( | 11096 HConstant* empty_fixed_array = Add<HConstant>( |
| 11100 isolate()->factory()->empty_fixed_array()); | 11097 isolate()->factory()->empty_fixed_array()); |
| (...skipping 1864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12965 if (ShouldProduceTraceOutput()) { | 12962 if (ShouldProduceTraceOutput()) { |
| 12966 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12963 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 12967 } | 12964 } |
| 12968 | 12965 |
| 12969 #ifdef DEBUG | 12966 #ifdef DEBUG |
| 12970 graph_->Verify(false); // No full verify. | 12967 graph_->Verify(false); // No full verify. |
| 12971 #endif | 12968 #endif |
| 12972 } | 12969 } |
| 12973 | 12970 |
| 12974 } } // namespace v8::internal | 12971 } } // namespace v8::internal |
| OLD | NEW |