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 |