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