| 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 5363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5374 HObjectAccess::ForContextSlot(lookup.slot_index)); | 5374 HObjectAccess::ForContextSlot(lookup.slot_index)); |
| 5375 return ast_context()->ReturnInstruction(result, expr->id()); | 5375 return ast_context()->ReturnInstruction(result, expr->id()); |
| 5376 } | 5376 } |
| 5377 } | 5377 } |
| 5378 | 5378 |
| 5379 LookupIterator it(global, variable->name(), LookupIterator::OWN); | 5379 LookupIterator it(global, variable->name(), LookupIterator::OWN); |
| 5380 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); | 5380 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); |
| 5381 | 5381 |
| 5382 if (type == kUseCell) { | 5382 if (type == kUseCell) { |
| 5383 Handle<PropertyCell> cell = it.GetPropertyCell(); | 5383 Handle<PropertyCell> cell = it.GetPropertyCell(); |
| 5384 PropertyCell::AddDependentCompilationInfo(cell, top_info()); | 5384 top_info()->dependencies()->AssumePropertyCell(cell); |
| 5385 if (it.property_details().cell_type() == PropertyCellType::kConstant) { | 5385 if (it.property_details().cell_type() == PropertyCellType::kConstant) { |
| 5386 Handle<Object> constant_object(cell->value(), isolate()); | 5386 Handle<Object> constant_object(cell->value(), isolate()); |
| 5387 if (constant_object->IsConsString()) { | 5387 if (constant_object->IsConsString()) { |
| 5388 constant_object = | 5388 constant_object = |
| 5389 String::Flatten(Handle<String>::cast(constant_object)); | 5389 String::Flatten(Handle<String>::cast(constant_object)); |
| 5390 } | 5390 } |
| 5391 HConstant* constant = New<HConstant>(constant_object); | 5391 HConstant* constant = New<HConstant>(constant_object); |
| 5392 return ast_context()->ReturnInstruction(constant, expr->id()); | 5392 return ast_context()->ReturnInstruction(constant, expr->id()); |
| 5393 } else { | 5393 } else { |
| 5394 HConstant* cell_constant = Add<HConstant>(cell); | 5394 HConstant* cell_constant = Add<HConstant>(cell); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5755 Add<HConstant>(literal_index), | 5755 Add<HConstant>(literal_index), |
| 5756 Add<HConstant>(constants), | 5756 Add<HConstant>(constants), |
| 5757 Add<HConstant>(flags)); | 5757 Add<HConstant>(flags)); |
| 5758 | 5758 |
| 5759 Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral; | 5759 Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral; |
| 5760 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 5760 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| 5761 Runtime::FunctionForId(function_id), | 5761 Runtime::FunctionForId(function_id), |
| 5762 4); | 5762 4); |
| 5763 | 5763 |
| 5764 // Register to deopt if the boilerplate ElementsKind changes. | 5764 // Register to deopt if the boilerplate ElementsKind changes. |
| 5765 AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info()); | 5765 top_info()->dependencies()->AssumeTransitionStable(site); |
| 5766 } | 5766 } |
| 5767 | 5767 |
| 5768 // The array is expected in the bailout environment during computation | 5768 // The array is expected in the bailout environment during computation |
| 5769 // of the property values and is the value of the entire expression. | 5769 // of the property values and is the value of the entire expression. |
| 5770 Push(literal); | 5770 Push(literal); |
| 5771 // The literal index is on the stack, too. | 5771 // The literal index is on the stack, too. |
| 5772 Push(Add<HConstant>(expr->literal_index())); | 5772 Push(Add<HConstant>(expr->literal_index())); |
| 5773 | 5773 |
| 5774 HInstruction* elements = NULL; | 5774 HInstruction* elements = NULL; |
| 5775 | 5775 |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6070 } | 6070 } |
| 6071 | 6071 |
| 6072 field_maps_.Sort(); | 6072 field_maps_.Sort(); |
| 6073 DCHECK_EQ(num_field_maps, field_maps_.length()); | 6073 DCHECK_EQ(num_field_maps, field_maps_.length()); |
| 6074 | 6074 |
| 6075 // Determine field HType from field HeapType. | 6075 // Determine field HType from field HeapType. |
| 6076 field_type_ = HType::FromType<HeapType>(field_type); | 6076 field_type_ = HType::FromType<HeapType>(field_type); |
| 6077 DCHECK(field_type_.IsHeapObject()); | 6077 DCHECK(field_type_.IsHeapObject()); |
| 6078 | 6078 |
| 6079 // Add dependency on the map that introduced the field. | 6079 // Add dependency on the map that introduced the field. |
| 6080 Map::AddDependentCompilationInfo(GetFieldOwnerFromMap(map), | 6080 top_info()->dependencies()->AssumeFieldType(GetFieldOwnerFromMap(map)); |
| 6081 DependentCode::kFieldTypeGroup, top_info()); | |
| 6082 return true; | 6081 return true; |
| 6083 } | 6082 } |
| 6084 | 6083 |
| 6085 | 6084 |
| 6086 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { | 6085 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { |
| 6087 Handle<Map> map = this->map(); | 6086 Handle<Map> map = this->map(); |
| 6088 | 6087 |
| 6089 while (map->prototype()->IsJSObject()) { | 6088 while (map->prototype()->IsJSObject()) { |
| 6090 holder_ = handle(JSObject::cast(map->prototype())); | 6089 holder_ = handle(JSObject::cast(map->prototype())); |
| 6091 if (holder_->map()->is_deprecated()) { | 6090 if (holder_->map()->is_deprecated()) { |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6540 DCHECK(instr->HasObservableSideEffects()); | 6539 DCHECK(instr->HasObservableSideEffects()); |
| 6541 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6540 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6542 return; | 6541 return; |
| 6543 } | 6542 } |
| 6544 } | 6543 } |
| 6545 | 6544 |
| 6546 LookupIterator it(global, var->name(), LookupIterator::OWN); | 6545 LookupIterator it(global, var->name(), LookupIterator::OWN); |
| 6547 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); | 6546 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); |
| 6548 if (type == kUseCell) { | 6547 if (type == kUseCell) { |
| 6549 Handle<PropertyCell> cell = it.GetPropertyCell(); | 6548 Handle<PropertyCell> cell = it.GetPropertyCell(); |
| 6550 PropertyCell::AddDependentCompilationInfo(cell, top_info()); | 6549 top_info()->dependencies()->AssumePropertyCell(cell); |
| 6551 if (it.property_details().cell_type() == PropertyCellType::kConstant) { | 6550 if (it.property_details().cell_type() == PropertyCellType::kConstant) { |
| 6552 Handle<Object> constant(cell->value(), isolate()); | 6551 Handle<Object> constant(cell->value(), isolate()); |
| 6553 if (value->IsConstant()) { | 6552 if (value->IsConstant()) { |
| 6554 HConstant* c_value = HConstant::cast(value); | 6553 HConstant* c_value = HConstant::cast(value); |
| 6555 if (!constant.is_identical_to(c_value->handle(isolate()))) { | 6554 if (!constant.is_identical_to(c_value->handle(isolate()))) { |
| 6556 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, | 6555 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, |
| 6557 Deoptimizer::EAGER); | 6556 Deoptimizer::EAGER); |
| 6558 } | 6557 } |
| 6559 } else { | 6558 } else { |
| 6560 HValue* c_constant = Add<HConstant>(constant); | 6559 HValue* c_constant = Add<HConstant>(constant); |
| (...skipping 2772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9333 int argument_count, | 9332 int argument_count, |
| 9334 Handle<AllocationSite> site) { | 9333 Handle<AllocationSite> site) { |
| 9335 DCHECK(!site.is_null()); | 9334 DCHECK(!site.is_null()); |
| 9336 DCHECK(argument_count >= 0 && argument_count <= 1); | 9335 DCHECK(argument_count >= 0 && argument_count <= 1); |
| 9337 NoObservableSideEffectsScope no_effects(this); | 9336 NoObservableSideEffectsScope no_effects(this); |
| 9338 | 9337 |
| 9339 // We should at least have the constructor on the expression stack. | 9338 // We should at least have the constructor on the expression stack. |
| 9340 HValue* constructor = environment()->ExpressionStackAt(argument_count); | 9339 HValue* constructor = environment()->ExpressionStackAt(argument_count); |
| 9341 | 9340 |
| 9342 // Register on the site for deoptimization if the transition feedback changes. | 9341 // Register on the site for deoptimization if the transition feedback changes. |
| 9343 AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info()); | 9342 top_info()->dependencies()->AssumeTransitionStable(site); |
| 9344 ElementsKind kind = site->GetElementsKind(); | 9343 ElementsKind kind = site->GetElementsKind(); |
| 9345 HInstruction* site_instruction = Add<HConstant>(site); | 9344 HInstruction* site_instruction = Add<HConstant>(site); |
| 9346 | 9345 |
| 9347 // In the single constant argument case, we may have to adjust elements kind | 9346 // In the single constant argument case, we may have to adjust elements kind |
| 9348 // to avoid creating a packed non-empty array. | 9347 // to avoid creating a packed non-empty array. |
| 9349 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { | 9348 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { |
| 9350 HValue* argument = environment()->Top(); | 9349 HValue* argument = environment()->Top(); |
| 9351 if (argument->IsConstant()) { | 9350 if (argument->IsConstant()) { |
| 9352 HConstant* constant_argument = HConstant::cast(argument); | 9351 HConstant* constant_argument = HConstant::cast(argument); |
| 9353 DCHECK(constant_argument->HasSmiValue()); | 9352 DCHECK(constant_argument->HasSmiValue()); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9469 | 9468 |
| 9470 // Allocate an instance of the implicit receiver object. | 9469 // Allocate an instance of the implicit receiver object. |
| 9471 HValue* size_in_bytes = Add<HConstant>(instance_size); | 9470 HValue* size_in_bytes = Add<HConstant>(instance_size); |
| 9472 HAllocationMode allocation_mode; | 9471 HAllocationMode allocation_mode; |
| 9473 if (FLAG_pretenuring_call_new) { | 9472 if (FLAG_pretenuring_call_new) { |
| 9474 if (FLAG_allocation_site_pretenuring) { | 9473 if (FLAG_allocation_site_pretenuring) { |
| 9475 // Try to use pretenuring feedback. | 9474 // Try to use pretenuring feedback. |
| 9476 Handle<AllocationSite> allocation_site = expr->allocation_site(); | 9475 Handle<AllocationSite> allocation_site = expr->allocation_site(); |
| 9477 allocation_mode = HAllocationMode(allocation_site); | 9476 allocation_mode = HAllocationMode(allocation_site); |
| 9478 // Take a dependency on allocation site. | 9477 // Take a dependency on allocation site. |
| 9479 AllocationSite::RegisterForDeoptOnTenureChange(allocation_site, | 9478 top_info()->dependencies()->AssumeTenuringDecision(allocation_site); |
| 9480 top_info()); | |
| 9481 } | 9479 } |
| 9482 } | 9480 } |
| 9483 | 9481 |
| 9484 HAllocate* receiver = BuildAllocate( | 9482 HAllocate* receiver = BuildAllocate( |
| 9485 size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode); | 9483 size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode); |
| 9486 receiver->set_known_initial_map(initial_map); | 9484 receiver->set_known_initial_map(initial_map); |
| 9487 | 9485 |
| 9488 // Initialize map and fields of the newly allocated object. | 9486 // Initialize map and fields of the newly allocated object. |
| 9489 { NoObservableSideEffectsScope no_effects(this); | 9487 { NoObservableSideEffectsScope no_effects(this); |
| 9490 DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE); | 9488 DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 9514 // Replace the constructor function with a newly allocated receiver using | 9512 // Replace the constructor function with a newly allocated receiver using |
| 9515 // the index of the receiver from the top of the expression stack. | 9513 // the index of the receiver from the top of the expression stack. |
| 9516 const int receiver_index = argument_count - 1; | 9514 const int receiver_index = argument_count - 1; |
| 9517 DCHECK(environment()->ExpressionStackAt(receiver_index) == function); | 9515 DCHECK(environment()->ExpressionStackAt(receiver_index) == function); |
| 9518 environment()->SetExpressionStackAt(receiver_index, receiver); | 9516 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 9519 | 9517 |
| 9520 if (TryInlineConstruct(expr, receiver)) { | 9518 if (TryInlineConstruct(expr, receiver)) { |
| 9521 // Inlining worked, add a dependency on the initial map to make sure that | 9519 // Inlining worked, add a dependency on the initial map to make sure that |
| 9522 // this code is deoptimized whenever the initial map of the constructor | 9520 // this code is deoptimized whenever the initial map of the constructor |
| 9523 // changes. | 9521 // changes. |
| 9524 Map::AddDependentCompilationInfo( | 9522 top_info()->dependencies()->AssumeInitialMapCantChange(initial_map); |
| 9525 initial_map, DependentCode::kInitialMapChangedGroup, top_info()); | |
| 9526 return; | 9523 return; |
| 9527 } | 9524 } |
| 9528 | 9525 |
| 9529 // TODO(mstarzinger): For now we remove the previous HAllocate and all | 9526 // TODO(mstarzinger): For now we remove the previous HAllocate and all |
| 9530 // corresponding instructions and instead add HPushArguments for the | 9527 // corresponding instructions and instead add HPushArguments for the |
| 9531 // arguments in case inlining failed. What we actually should do is for | 9528 // arguments in case inlining failed. What we actually should do is for |
| 9532 // inlining to try to build a subgraph without mutating the parent graph. | 9529 // inlining to try to build a subgraph without mutating the parent graph. |
| 9533 HInstruction* instr = current_block()->last(); | 9530 HInstruction* instr = current_block()->last(); |
| 9534 do { | 9531 do { |
| 9535 HInstruction* prev_instr = instr->previous(); | 9532 HInstruction* prev_instr = instr->previous(); |
| (...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10489 if (!left_string.is_null() && !right_string.is_null()) { | 10486 if (!left_string.is_null() && !right_string.is_null()) { |
| 10490 return AddUncasted<HStringAdd>( | 10487 return AddUncasted<HStringAdd>( |
| 10491 left, right, allocation_mode.GetPretenureMode(), | 10488 left, right, allocation_mode.GetPretenureMode(), |
| 10492 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); | 10489 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); |
| 10493 } | 10490 } |
| 10494 | 10491 |
| 10495 // Register the dependent code with the allocation site. | 10492 // Register the dependent code with the allocation site. |
| 10496 if (!allocation_mode.feedback_site().is_null()) { | 10493 if (!allocation_mode.feedback_site().is_null()) { |
| 10497 DCHECK(!graph()->info()->IsStub()); | 10494 DCHECK(!graph()->info()->IsStub()); |
| 10498 Handle<AllocationSite> site(allocation_mode.feedback_site()); | 10495 Handle<AllocationSite> site(allocation_mode.feedback_site()); |
| 10499 AllocationSite::RegisterForDeoptOnTenureChange(site, top_info()); | 10496 top_info()->dependencies()->AssumeTenuringDecision(site); |
| 10500 } | 10497 } |
| 10501 | 10498 |
| 10502 // Inline the string addition into the stub when creating allocation | 10499 // Inline the string addition into the stub when creating allocation |
| 10503 // mementos to gather allocation site feedback, or if we can statically | 10500 // mementos to gather allocation site feedback, or if we can statically |
| 10504 // infer that we're going to create a cons string. | 10501 // infer that we're going to create a cons string. |
| 10505 if ((graph()->info()->IsStub() && | 10502 if ((graph()->info()->IsStub() && |
| 10506 allocation_mode.CreateAllocationMementos()) || | 10503 allocation_mode.CreateAllocationMementos()) || |
| 10507 (left->IsConstant() && | 10504 (left->IsConstant() && |
| 10508 HConstant::cast(left)->HasStringValue() && | 10505 HConstant::cast(left)->HasStringValue() && |
| 10509 HConstant::cast(left)->StringValue()->length() + 1 >= | 10506 HConstant::cast(left)->StringValue()->length() + 1 >= |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11060 | 11057 |
| 11061 HType type = instance_type == JS_ARRAY_TYPE | 11058 HType type = instance_type == JS_ARRAY_TYPE |
| 11062 ? HType::JSArray() : HType::JSObject(); | 11059 ? HType::JSArray() : HType::JSObject(); |
| 11063 HValue* object_size_constant = Add<HConstant>( | 11060 HValue* object_size_constant = Add<HConstant>( |
| 11064 boilerplate_object->map()->instance_size()); | 11061 boilerplate_object->map()->instance_size()); |
| 11065 | 11062 |
| 11066 PretenureFlag pretenure_flag = NOT_TENURED; | 11063 PretenureFlag pretenure_flag = NOT_TENURED; |
| 11067 Handle<AllocationSite> site(site_context->current()); | 11064 Handle<AllocationSite> site(site_context->current()); |
| 11068 if (FLAG_allocation_site_pretenuring) { | 11065 if (FLAG_allocation_site_pretenuring) { |
| 11069 pretenure_flag = site_context->current()->GetPretenureMode(); | 11066 pretenure_flag = site_context->current()->GetPretenureMode(); |
| 11070 AllocationSite::RegisterForDeoptOnTenureChange(site, top_info()); | 11067 top_info()->dependencies()->AssumeTenuringDecision(site); |
| 11071 } | 11068 } |
| 11072 | 11069 |
| 11073 AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info()); | 11070 top_info()->dependencies()->AssumeTransitionStable(site); |
| 11074 | 11071 |
| 11075 HInstruction* object = Add<HAllocate>(object_size_constant, type, | 11072 HInstruction* object = Add<HAllocate>(object_size_constant, type, |
| 11076 pretenure_flag, instance_type, site_context->current()); | 11073 pretenure_flag, instance_type, site_context->current()); |
| 11077 | 11074 |
| 11078 // If allocation folding reaches Page::kMaxRegularHeapObjectSize the | 11075 // If allocation folding reaches Page::kMaxRegularHeapObjectSize the |
| 11079 // elements array may not get folded into the object. Hence, we set the | 11076 // elements array may not get folded into the object. Hence, we set the |
| 11080 // elements pointer to empty fixed array and let store elimination remove | 11077 // elements pointer to empty fixed array and let store elimination remove |
| 11081 // this store in the folding case. | 11078 // this store in the folding case. |
| 11082 HConstant* empty_fixed_array = Add<HConstant>( | 11079 HConstant* empty_fixed_array = Add<HConstant>( |
| 11083 isolate()->factory()->empty_fixed_array()); | 11080 isolate()->factory()->empty_fixed_array()); |
| (...skipping 1864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12948 if (ShouldProduceTraceOutput()) { | 12945 if (ShouldProduceTraceOutput()) { |
| 12949 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12946 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 12950 } | 12947 } |
| 12951 | 12948 |
| 12952 #ifdef DEBUG | 12949 #ifdef DEBUG |
| 12953 graph_->Verify(false); // No full verify. | 12950 graph_->Verify(false); // No full verify. |
| 12954 #endif | 12951 #endif |
| 12955 } | 12952 } |
| 12956 | 12953 |
| 12957 } } // namespace v8::internal | 12954 } } // namespace v8::internal |
| OLD | NEW |