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 |