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 |