| 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 5333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5344 HObjectAccess::ForContextSlot(lookup.slot_index)); | 5344 HObjectAccess::ForContextSlot(lookup.slot_index)); |
| 5345 return ast_context()->ReturnInstruction(result, expr->id()); | 5345 return ast_context()->ReturnInstruction(result, expr->id()); |
| 5346 } | 5346 } |
| 5347 } | 5347 } |
| 5348 | 5348 |
| 5349 LookupIterator it(global, variable->name(), LookupIterator::OWN); | 5349 LookupIterator it(global, variable->name(), LookupIterator::OWN); |
| 5350 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); | 5350 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); |
| 5351 | 5351 |
| 5352 if (type == kUseCell) { | 5352 if (type == kUseCell) { |
| 5353 Handle<PropertyCell> cell = it.GetPropertyCell(); | 5353 Handle<PropertyCell> cell = it.GetPropertyCell(); |
| 5354 top_info()->dependencies()->AssumePropertyCell(cell); | 5354 PropertyCell::AddDependentCompilationInfo(cell, top_info()); |
| 5355 if (it.property_details().cell_type() == PropertyCellType::kConstant) { | 5355 if (it.property_details().cell_type() == PropertyCellType::kConstant) { |
| 5356 Handle<Object> constant_object(cell->value(), isolate()); | 5356 Handle<Object> constant_object(cell->value(), isolate()); |
| 5357 if (constant_object->IsConsString()) { | 5357 if (constant_object->IsConsString()) { |
| 5358 constant_object = | 5358 constant_object = |
| 5359 String::Flatten(Handle<String>::cast(constant_object)); | 5359 String::Flatten(Handle<String>::cast(constant_object)); |
| 5360 } | 5360 } |
| 5361 HConstant* constant = New<HConstant>(constant_object); | 5361 HConstant* constant = New<HConstant>(constant_object); |
| 5362 return ast_context()->ReturnInstruction(constant, expr->id()); | 5362 return ast_context()->ReturnInstruction(constant, expr->id()); |
| 5363 } else { | 5363 } else { |
| 5364 HConstant* cell_constant = Add<HConstant>(cell); | 5364 HConstant* cell_constant = Add<HConstant>(cell); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5725 Add<HConstant>(literal_index), | 5725 Add<HConstant>(literal_index), |
| 5726 Add<HConstant>(constants), | 5726 Add<HConstant>(constants), |
| 5727 Add<HConstant>(flags)); | 5727 Add<HConstant>(flags)); |
| 5728 | 5728 |
| 5729 Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral; | 5729 Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral; |
| 5730 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 5730 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| 5731 Runtime::FunctionForId(function_id), | 5731 Runtime::FunctionForId(function_id), |
| 5732 4); | 5732 4); |
| 5733 | 5733 |
| 5734 // Register to deopt if the boilerplate ElementsKind changes. | 5734 // Register to deopt if the boilerplate ElementsKind changes. |
| 5735 top_info()->dependencies()->AssumeTransitionStable(site); | 5735 AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info()); |
| 5736 } | 5736 } |
| 5737 | 5737 |
| 5738 // The array is expected in the bailout environment during computation | 5738 // The array is expected in the bailout environment during computation |
| 5739 // of the property values and is the value of the entire expression. | 5739 // of the property values and is the value of the entire expression. |
| 5740 Push(literal); | 5740 Push(literal); |
| 5741 // The literal index is on the stack, too. | 5741 // The literal index is on the stack, too. |
| 5742 Push(Add<HConstant>(expr->literal_index())); | 5742 Push(Add<HConstant>(expr->literal_index())); |
| 5743 | 5743 |
| 5744 HInstruction* elements = NULL; | 5744 HInstruction* elements = NULL; |
| 5745 | 5745 |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6040 } | 6040 } |
| 6041 | 6041 |
| 6042 field_maps_.Sort(); | 6042 field_maps_.Sort(); |
| 6043 DCHECK_EQ(num_field_maps, field_maps_.length()); | 6043 DCHECK_EQ(num_field_maps, field_maps_.length()); |
| 6044 | 6044 |
| 6045 // Determine field HType from field HeapType. | 6045 // Determine field HType from field HeapType. |
| 6046 field_type_ = HType::FromType<HeapType>(field_type); | 6046 field_type_ = HType::FromType<HeapType>(field_type); |
| 6047 DCHECK(field_type_.IsHeapObject()); | 6047 DCHECK(field_type_.IsHeapObject()); |
| 6048 | 6048 |
| 6049 // Add dependency on the map that introduced the field. | 6049 // Add dependency on the map that introduced the field. |
| 6050 top_info()->dependencies()->AssumeFieldType(GetFieldOwnerFromMap(map)); | 6050 Map::AddDependentCompilationInfo(GetFieldOwnerFromMap(map), |
| 6051 DependentCode::kFieldTypeGroup, top_info()); |
| 6051 return true; | 6052 return true; |
| 6052 } | 6053 } |
| 6053 | 6054 |
| 6054 | 6055 |
| 6055 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { | 6056 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { |
| 6056 Handle<Map> map = this->map(); | 6057 Handle<Map> map = this->map(); |
| 6057 | 6058 |
| 6058 while (map->prototype()->IsJSObject()) { | 6059 while (map->prototype()->IsJSObject()) { |
| 6059 holder_ = handle(JSObject::cast(map->prototype())); | 6060 holder_ = handle(JSObject::cast(map->prototype())); |
| 6060 if (holder_->map()->is_deprecated()) { | 6061 if (holder_->map()->is_deprecated()) { |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6509 DCHECK(instr->HasObservableSideEffects()); | 6510 DCHECK(instr->HasObservableSideEffects()); |
| 6510 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6511 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6511 return; | 6512 return; |
| 6512 } | 6513 } |
| 6513 } | 6514 } |
| 6514 | 6515 |
| 6515 LookupIterator it(global, var->name(), LookupIterator::OWN); | 6516 LookupIterator it(global, var->name(), LookupIterator::OWN); |
| 6516 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); | 6517 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); |
| 6517 if (type == kUseCell) { | 6518 if (type == kUseCell) { |
| 6518 Handle<PropertyCell> cell = it.GetPropertyCell(); | 6519 Handle<PropertyCell> cell = it.GetPropertyCell(); |
| 6519 top_info()->dependencies()->AssumePropertyCell(cell); | 6520 PropertyCell::AddDependentCompilationInfo(cell, top_info()); |
| 6520 if (it.property_details().cell_type() == PropertyCellType::kConstant) { | 6521 if (it.property_details().cell_type() == PropertyCellType::kConstant) { |
| 6521 Handle<Object> constant(cell->value(), isolate()); | 6522 Handle<Object> constant(cell->value(), isolate()); |
| 6522 if (value->IsConstant()) { | 6523 if (value->IsConstant()) { |
| 6523 HConstant* c_value = HConstant::cast(value); | 6524 HConstant* c_value = HConstant::cast(value); |
| 6524 if (!constant.is_identical_to(c_value->handle(isolate()))) { | 6525 if (!constant.is_identical_to(c_value->handle(isolate()))) { |
| 6525 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, | 6526 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, |
| 6526 Deoptimizer::EAGER); | 6527 Deoptimizer::EAGER); |
| 6527 } | 6528 } |
| 6528 } else { | 6529 } else { |
| 6529 HValue* c_constant = Add<HConstant>(constant); | 6530 HValue* c_constant = Add<HConstant>(constant); |
| (...skipping 2773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9303 int argument_count, | 9304 int argument_count, |
| 9304 Handle<AllocationSite> site) { | 9305 Handle<AllocationSite> site) { |
| 9305 DCHECK(!site.is_null()); | 9306 DCHECK(!site.is_null()); |
| 9306 DCHECK(argument_count >= 0 && argument_count <= 1); | 9307 DCHECK(argument_count >= 0 && argument_count <= 1); |
| 9307 NoObservableSideEffectsScope no_effects(this); | 9308 NoObservableSideEffectsScope no_effects(this); |
| 9308 | 9309 |
| 9309 // We should at least have the constructor on the expression stack. | 9310 // We should at least have the constructor on the expression stack. |
| 9310 HValue* constructor = environment()->ExpressionStackAt(argument_count); | 9311 HValue* constructor = environment()->ExpressionStackAt(argument_count); |
| 9311 | 9312 |
| 9312 // Register on the site for deoptimization if the transition feedback changes. | 9313 // Register on the site for deoptimization if the transition feedback changes. |
| 9313 top_info()->dependencies()->AssumeTransitionStable(site); | 9314 AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info()); |
| 9314 ElementsKind kind = site->GetElementsKind(); | 9315 ElementsKind kind = site->GetElementsKind(); |
| 9315 HInstruction* site_instruction = Add<HConstant>(site); | 9316 HInstruction* site_instruction = Add<HConstant>(site); |
| 9316 | 9317 |
| 9317 // In the single constant argument case, we may have to adjust elements kind | 9318 // In the single constant argument case, we may have to adjust elements kind |
| 9318 // to avoid creating a packed non-empty array. | 9319 // to avoid creating a packed non-empty array. |
| 9319 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { | 9320 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { |
| 9320 HValue* argument = environment()->Top(); | 9321 HValue* argument = environment()->Top(); |
| 9321 if (argument->IsConstant()) { | 9322 if (argument->IsConstant()) { |
| 9322 HConstant* constant_argument = HConstant::cast(argument); | 9323 HConstant* constant_argument = HConstant::cast(argument); |
| 9323 DCHECK(constant_argument->HasSmiValue()); | 9324 DCHECK(constant_argument->HasSmiValue()); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9439 | 9440 |
| 9440 // Allocate an instance of the implicit receiver object. | 9441 // Allocate an instance of the implicit receiver object. |
| 9441 HValue* size_in_bytes = Add<HConstant>(instance_size); | 9442 HValue* size_in_bytes = Add<HConstant>(instance_size); |
| 9442 HAllocationMode allocation_mode; | 9443 HAllocationMode allocation_mode; |
| 9443 if (FLAG_pretenuring_call_new) { | 9444 if (FLAG_pretenuring_call_new) { |
| 9444 if (FLAG_allocation_site_pretenuring) { | 9445 if (FLAG_allocation_site_pretenuring) { |
| 9445 // Try to use pretenuring feedback. | 9446 // Try to use pretenuring feedback. |
| 9446 Handle<AllocationSite> allocation_site = expr->allocation_site(); | 9447 Handle<AllocationSite> allocation_site = expr->allocation_site(); |
| 9447 allocation_mode = HAllocationMode(allocation_site); | 9448 allocation_mode = HAllocationMode(allocation_site); |
| 9448 // Take a dependency on allocation site. | 9449 // Take a dependency on allocation site. |
| 9449 top_info()->dependencies()->AssumeTenuringDecision(allocation_site); | 9450 AllocationSite::RegisterForDeoptOnTenureChange(allocation_site, |
| 9451 top_info()); |
| 9450 } | 9452 } |
| 9451 } | 9453 } |
| 9452 | 9454 |
| 9453 HAllocate* receiver = BuildAllocate( | 9455 HAllocate* receiver = BuildAllocate( |
| 9454 size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode); | 9456 size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode); |
| 9455 receiver->set_known_initial_map(initial_map); | 9457 receiver->set_known_initial_map(initial_map); |
| 9456 | 9458 |
| 9457 // Initialize map and fields of the newly allocated object. | 9459 // Initialize map and fields of the newly allocated object. |
| 9458 { NoObservableSideEffectsScope no_effects(this); | 9460 { NoObservableSideEffectsScope no_effects(this); |
| 9459 DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE); | 9461 DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 9483 // Replace the constructor function with a newly allocated receiver using | 9485 // Replace the constructor function with a newly allocated receiver using |
| 9484 // the index of the receiver from the top of the expression stack. | 9486 // the index of the receiver from the top of the expression stack. |
| 9485 const int receiver_index = argument_count - 1; | 9487 const int receiver_index = argument_count - 1; |
| 9486 DCHECK(environment()->ExpressionStackAt(receiver_index) == function); | 9488 DCHECK(environment()->ExpressionStackAt(receiver_index) == function); |
| 9487 environment()->SetExpressionStackAt(receiver_index, receiver); | 9489 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 9488 | 9490 |
| 9489 if (TryInlineConstruct(expr, receiver)) { | 9491 if (TryInlineConstruct(expr, receiver)) { |
| 9490 // Inlining worked, add a dependency on the initial map to make sure that | 9492 // Inlining worked, add a dependency on the initial map to make sure that |
| 9491 // this code is deoptimized whenever the initial map of the constructor | 9493 // this code is deoptimized whenever the initial map of the constructor |
| 9492 // changes. | 9494 // changes. |
| 9493 top_info()->dependencies()->AssumeInitialMapCantChange(initial_map); | 9495 Map::AddDependentCompilationInfo( |
| 9496 initial_map, DependentCode::kInitialMapChangedGroup, top_info()); |
| 9494 return; | 9497 return; |
| 9495 } | 9498 } |
| 9496 | 9499 |
| 9497 // TODO(mstarzinger): For now we remove the previous HAllocate and all | 9500 // TODO(mstarzinger): For now we remove the previous HAllocate and all |
| 9498 // corresponding instructions and instead add HPushArguments for the | 9501 // corresponding instructions and instead add HPushArguments for the |
| 9499 // arguments in case inlining failed. What we actually should do is for | 9502 // arguments in case inlining failed. What we actually should do is for |
| 9500 // inlining to try to build a subgraph without mutating the parent graph. | 9503 // inlining to try to build a subgraph without mutating the parent graph. |
| 9501 HInstruction* instr = current_block()->last(); | 9504 HInstruction* instr = current_block()->last(); |
| 9502 do { | 9505 do { |
| 9503 HInstruction* prev_instr = instr->previous(); | 9506 HInstruction* prev_instr = instr->previous(); |
| (...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10457 if (!left_string.is_null() && !right_string.is_null()) { | 10460 if (!left_string.is_null() && !right_string.is_null()) { |
| 10458 return AddUncasted<HStringAdd>( | 10461 return AddUncasted<HStringAdd>( |
| 10459 left, right, allocation_mode.GetPretenureMode(), | 10462 left, right, allocation_mode.GetPretenureMode(), |
| 10460 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); | 10463 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); |
| 10461 } | 10464 } |
| 10462 | 10465 |
| 10463 // Register the dependent code with the allocation site. | 10466 // Register the dependent code with the allocation site. |
| 10464 if (!allocation_mode.feedback_site().is_null()) { | 10467 if (!allocation_mode.feedback_site().is_null()) { |
| 10465 DCHECK(!graph()->info()->IsStub()); | 10468 DCHECK(!graph()->info()->IsStub()); |
| 10466 Handle<AllocationSite> site(allocation_mode.feedback_site()); | 10469 Handle<AllocationSite> site(allocation_mode.feedback_site()); |
| 10467 top_info()->dependencies()->AssumeTenuringDecision(site); | 10470 AllocationSite::RegisterForDeoptOnTenureChange(site, top_info()); |
| 10468 } | 10471 } |
| 10469 | 10472 |
| 10470 // Inline the string addition into the stub when creating allocation | 10473 // Inline the string addition into the stub when creating allocation |
| 10471 // mementos to gather allocation site feedback, or if we can statically | 10474 // mementos to gather allocation site feedback, or if we can statically |
| 10472 // infer that we're going to create a cons string. | 10475 // infer that we're going to create a cons string. |
| 10473 if ((graph()->info()->IsStub() && | 10476 if ((graph()->info()->IsStub() && |
| 10474 allocation_mode.CreateAllocationMementos()) || | 10477 allocation_mode.CreateAllocationMementos()) || |
| 10475 (left->IsConstant() && | 10478 (left->IsConstant() && |
| 10476 HConstant::cast(left)->HasStringValue() && | 10479 HConstant::cast(left)->HasStringValue() && |
| 10477 HConstant::cast(left)->StringValue()->length() + 1 >= | 10480 HConstant::cast(left)->StringValue()->length() + 1 >= |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11028 | 11031 |
| 11029 HType type = instance_type == JS_ARRAY_TYPE | 11032 HType type = instance_type == JS_ARRAY_TYPE |
| 11030 ? HType::JSArray() : HType::JSObject(); | 11033 ? HType::JSArray() : HType::JSObject(); |
| 11031 HValue* object_size_constant = Add<HConstant>( | 11034 HValue* object_size_constant = Add<HConstant>( |
| 11032 boilerplate_object->map()->instance_size()); | 11035 boilerplate_object->map()->instance_size()); |
| 11033 | 11036 |
| 11034 PretenureFlag pretenure_flag = NOT_TENURED; | 11037 PretenureFlag pretenure_flag = NOT_TENURED; |
| 11035 Handle<AllocationSite> site(site_context->current()); | 11038 Handle<AllocationSite> site(site_context->current()); |
| 11036 if (FLAG_allocation_site_pretenuring) { | 11039 if (FLAG_allocation_site_pretenuring) { |
| 11037 pretenure_flag = site_context->current()->GetPretenureMode(); | 11040 pretenure_flag = site_context->current()->GetPretenureMode(); |
| 11038 top_info()->dependencies()->AssumeTenuringDecision(site); | 11041 AllocationSite::RegisterForDeoptOnTenureChange(site, top_info()); |
| 11039 } | 11042 } |
| 11040 | 11043 |
| 11041 top_info()->dependencies()->AssumeTransitionStable(site); | 11044 AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info()); |
| 11042 | 11045 |
| 11043 HInstruction* object = Add<HAllocate>(object_size_constant, type, | 11046 HInstruction* object = Add<HAllocate>(object_size_constant, type, |
| 11044 pretenure_flag, instance_type, site_context->current()); | 11047 pretenure_flag, instance_type, site_context->current()); |
| 11045 | 11048 |
| 11046 // If allocation folding reaches Page::kMaxRegularHeapObjectSize the | 11049 // If allocation folding reaches Page::kMaxRegularHeapObjectSize the |
| 11047 // elements array may not get folded into the object. Hence, we set the | 11050 // elements array may not get folded into the object. Hence, we set the |
| 11048 // elements pointer to empty fixed array and let store elimination remove | 11051 // elements pointer to empty fixed array and let store elimination remove |
| 11049 // this store in the folding case. | 11052 // this store in the folding case. |
| 11050 HConstant* empty_fixed_array = Add<HConstant>( | 11053 HConstant* empty_fixed_array = Add<HConstant>( |
| 11051 isolate()->factory()->empty_fixed_array()); | 11054 isolate()->factory()->empty_fixed_array()); |
| (...skipping 1864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12916 if (ShouldProduceTraceOutput()) { | 12919 if (ShouldProduceTraceOutput()) { |
| 12917 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12920 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 12918 } | 12921 } |
| 12919 | 12922 |
| 12920 #ifdef DEBUG | 12923 #ifdef DEBUG |
| 12921 graph_->Verify(false); // No full verify. | 12924 graph_->Verify(false); // No full verify. |
| 12922 #endif | 12925 #endif |
| 12923 } | 12926 } |
| 12924 | 12927 |
| 12925 } } // namespace v8::internal | 12928 } } // namespace v8::internal |
| OLD | NEW |